下面的 PL/SQL 块查找表中所有锁定的行。其他答案只找到阻塞 session,找到实际锁定的 rows 需要读取和测试每一行。
(但是,您可能不需要运行此代码。如果您遇到锁定问题,使用GV$SESSION.BLOCKING_SESSION 和其他相关数据字典视图通常更容易找到罪魁祸首。请在运行前尝试其他方法这个非常慢的代码。)
首先,让我们创建一个示例表和一些数据。在会话 #1 中运行它。
--Sample schema.
create table test_locking(a number);
insert into test_locking values(1);
insert into test_locking values(2);
commit;
update test_locking set a = a+1 where a = 1;
在会话 #2 中,创建一个表来保存锁定的 ROWID。
--Create table to hold locked ROWIDs.
create table locked_rowids(the_rowid rowid);
--Remove old rows if table is already created:
--delete from locked_rowids;
--commit;
在会话 #2 中,运行此 PL/SQL 块以读取整个表、探测每一行并存储锁定的 ROWID。请注意,这可能会非常缓慢。在此查询的实际版本中,将对 TEST_LOCKING 的两个引用更改为您自己的表。
--Save all locked ROWIDs from a table.
--WARNING: This PL/SQL block will be slow and will temporarily lock rows.
--You probably don't need this information - it's usually good enough to know
--what other sessions are locking a statement, which you can find in
--GV$SESSION.BLOCKING_SESSION.
declare
v_resource_busy exception;
pragma exception_init(v_resource_busy, -00054);
v_throwaway number;
type rowid_nt is table of rowid;
v_rowids rowid_nt := rowid_nt();
begin
--Loop through all the rows in the table.
for all_rows in
(
select rowid
from test_locking
) loop
--Try to look each row.
begin
select 1
into v_throwaway
from test_locking
where rowid = all_rows.rowid
for update nowait;
--If it doesn't lock, then record the ROWID.
exception when v_resource_busy then
v_rowids.extend;
v_rowids(v_rowids.count) := all_rows.rowid;
end;
rollback;
end loop;
--Display count:
dbms_output.put_line('Rows locked: '||v_rowids.count);
--Save all the ROWIDs.
--(Row-by-row because ROWID type is weird and doesn't work in types.)
for i in 1 .. v_rowids.count loop
insert into locked_rowids values(v_rowids(i));
end loop;
commit;
end;
/
最后,我们可以通过加入 LOCKED_ROWIDS 表来查看锁定的行。
--Display locked rows.
select *
from test_locking
where rowid in (select the_rowid from locked_rowids);
A
-
1