在v$session视图中有四个字段,如下:
ROW_WAIT_OBJ# | NUMBER | Object ID for the table containing the row specified in ROW_WAIT_ROW# |
ROW_WAIT_FILE# | NUMBER |
Identifier for the datafile containing the row specified in ROW_WAIT_ROW#.This column is valid only if the session is currently waiting for another transaction to commit and the value of ROW_WAIT_OBJ# is not -1. |
ROW_WAIT_BLOCK# | NUMBER |
Identifier for the block containing the row specified in ROW_WAIT_ROW#.This column is valid only if the session is currently waiting for another transaction to commit and the value of ROW_WAIT_OBJ# is not -1. |
ROW_WAIT_ROW# | NUMBER | Current row being locked. This column is valid only if the session is currently waiting for another transaction to commit and the value of ROW_WAIT_OBJ# is not -1 |
当我们在遭遇:enq: TX - row lock contention,这些等待事件时,可通过dbms_rowid.rowid_create(xx,xx,xx,xx,xx)来创建等待的数据行的rowid.
而在此要注意的是这个内建的procedure的第二个参数,先看下oracle 的doc对于dbms_rowid.rowid_create的解释:
BMS_ROWID.ROWID_CREATE (
rowid_type IN NUMBER,
object_number IN NUMBER,
relative_fno IN NUMBER,
block_number IN NUMBER,
row_number IN NUMBER)
参数:
rowid_type:rowid类型(restricted或者extended)。设置rowid_type为0时,代表restricted ROWID(此时,将忽略参数object_number):设置rowid_type为1时,代表extended ROWID。
object_number:数据对象编号(仅restricted类型rowid可用)。
relative_fno:所在数据文件编号。
block_number:该数据文件中的数据块编号。
row_number:在该块中的行编号。
第二个参数写的是object_number,而其解释中的是数据对象编号,其对应的应该是dba_objects中的data_object_id字段。如下:
SQL> desc dba_objects
名称 是否为空? 类型
----------------------------------------- -------- ------------------------
OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(128)
SUBOBJECT_NAME VARCHAR2(30)
OBJECT_ID NUMBER
DATA_OBJECT_ID NUMBER
OBJECT_TYPE VARCHAR2(19)
CREATED DATE
LAST_DDL_TIME DATE
TIMESTAMP VARCHAR2(19)
STATUS VARCHAR2(7)
TEMPORARY VARCHAR2(1)
GENERATED VARCHAR2(1)
SECONDARY VARCHAR2(1)
一般而言,object_id是这个table在oracle中的对象编号,而data_object_id,指的是数据物理存放的对象编号,应该是段编号。通常情况下,这二者相等,当然分区表除外(分区表只有一个object_id,有多个data_object_id)。
当我们对table行truncate,move等操作的时候,可能就会引起二者不相等,如下例证:
SQL> drop table t1;
表已删除。
SQL> create table t1(id number);
表已创建。
SQL> col object_name for a20
SQL> select object_id,data_object_id,object_name from dba_objects where object_name='T1';
OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- --------------------
52961 52961 T1
(1):此时t1是个空表,无数据,我们进行truncate操作。
SQL> truncate table t1;
表被截断。
SQL> select object_id,data_object_id,object_name from dba_objects where object_name='T1';
OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- --------------------
52961 52961 T1
我们发现空表时进行truncate操作,object_id 和data_object_id仍然是相等的。
(2):插入数据,再次truncate
SQL> insert into t1(id) values(1);
已创建 1 行。
SQL> commit;
提交完成。
SQL> select * from t1;
ID
----------
1
SQL> truncate table t1;
表被截断。
SQL> select object_id,data_object_id,object_name from dba_objects where object_name='T1';
OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- --------------------
52961 52962 T1
此时,二者已经不相等了。下面测试move操作。
(3):表中无数据时进行move操作。
下面是使用dbms_rowid.rowid_create的一个例子
sys@JINGYONG> select rowid, t.*,dbms_rowid.rowid_relative_fno(rowid) relative_fno , 2 dbms_rowid.rowid_object(rowid) object_number , 3 dbms_rowid.rowid_block_number(rowid) block_number , 4 dbms_rowid.rowid_row_number(rowid) row_number 5 from t where rownum<2; ROWID ID TEXT RELATIVE_FNO OBJECT_NUMBER BLOCK_NUMBER ROW_NUMBER ------------------ ---------- ------------------------------ ------------ ------------- ------------ ---------- AAANB1AABAAAPAaAAA 20 ICOL$ 1 53365 61466 0 sys@JINGYONG> select data_object_id from dba_objects where object_id=53365; DATA_OBJECT_ID -------------- 53365 sys@JINGYONG> select dbms_rowid.rowid_create(1,53365,1,61466,0) create_rowid fr om dual; CREATE_ROWID ------------------ AAANB1AABAAAPAaAAA
通过dbms_rowid.rowid_create(1,53365,1,61466,0)构造的rowid与原始的rowid是一样的.
参数的意思:
1表示rowid的类型为扩展rowid,类型为1;
data_object_id 为53365,也就是文中t表对象的id;
数据文件id为1 ,即system表空间文件;
块的编号为61466号; 行数为第一行(第一行为值0) 。
通过dbms_rowid.rowid_create函数查询被锁定的具体行
查询被锁的会话和持有锁的会话,如果是exclusive锁则xidusn非零的表示已经执行并持有锁
column o_name format a10
column lock_type format a20
column object_name format a15
select rpad(oracle_username,10) o_name,
session_id sid,
decode(locked_mode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_type,
object_name,
all_objects.object_id,
xidusn,
xidslot,
xidsqn
from v$locked_object,all_objects
where v$locked_object.object_id=all_objects.object_id;
O_NAME SID LOCK_TYPE OBJECT_NAME OBJECT_ID XIDUSN XIDSLOT XIDSQN
---------- ------- -------------------- --------------- -------------- ---------- ------------ ----------
SYS 145 Row Exclusive T 53365 8 17 724
SYS 148 Row Exclusive T 53365 0 0 0
下面的查询可以得到被锁定的session,被锁定的对象id和row number
select sid,
row_wait_obj# object_id,
row_wait_file# file_no,
row_wait_block# block,
row_wait_row# row_num
from v$session
where row_wait_obj#=&object_id;
Enter value for object_id: 53365
old 7: where row_wait_obj#=&object_id
new 7: where row_wait_obj#=53365
SID OBJECT_ID FILE_NO BLOCK ROW_NUM
---------- -------------- ---------- ---------- ----------
148 51207 1 61466 0
如果要对应行rowid则:
sys@JINGYONG> select dbms_rowid.rowid_create(1,53365,1,61466,0) create_rowid from dual;
CREATE_ROWID
------------------
AAANB1AABAAAPAaAAA
有了rowid,具体的行就能定位了