1.oracle中锁的分类
oracle里的锁分为DDL,DML锁
DML锁又可以分为,行锁、表锁、死锁
行锁:当事务执行数据库插入、更新、删除操作时,该事务自动获得操作表中操作行的排它锁。
表级锁:当事务获得行锁后,此事务也将自动获得该行的表锁(共享锁),以防止其它事务进行DDL语句影响记录行的更新。事务也可以在进行过程中获得共享锁或排它锁,只有当事务显示使用LOCK
TABLE语句显示的定义一个排它锁时,事务才会获得表上的排它锁,也可使用LOCK TABLE显示的定义一个表级的共享锁(LOCK
TABLE具体用法请参考相关文档)。
死锁:当两个事务需要一组有冲突的锁,而不能将事务继续下去的话,就出现死锁。
如事务1在表A行记录#3中有一排它锁,并等待事务2在表A中记录#4中排它锁的释放,而事务2在表A记录行#4中有一排它锁,并等待事务1在表A中记录#3中排它锁的释放,事务1与事务2彼此等待,因此就造成了死锁。死锁一般是因拙劣的事务设计而产生。
DDL锁又可以分为:排它DDL锁、共享DDL锁、分析锁
排它DDL锁:创建、修改、删除一个数据库对象的DDL语句获得操作对象的 排它锁。如使用alter
table语句时,为了维护数据的完成性、一致性、合法性,该事务获得一排它DDL锁。
共享DDL锁:需在数据库对象之间建立相互依赖关系的DDL语句通常需共享获得DDL锁。
如创建一个包,该包中的过程与函数引用了不同的数据库表,当编译此包时,该事务就获得了引用表的共享DDL锁。
分析锁:ORACLE使用共享池存储分析与优化过的SQL语句及PL/SQL程序,使运行相同语句的应用速度更快。一个在共享池中缓存的对象获得它所引用数据库对象的分析锁。分析锁是一种独特的DDL锁类型,ORACLE使用它追踪共享池对象及它所引用数据库对象之间的依赖关系。当一个事务修改或删除了共享池持有分析锁的数据库对象时,ORACLE使共享池中的对象作废,下次在引用这条SQL/PLSQL语句时,ORACLE重新分析编译此语句。
2.oracle数据库在什么情况下会锁表
引起锁的情况很多,例如:
Select ... for update
;
Lock Table ;
外键约束;
Alter table ...
等等。。。
3.锁表后的解决办法
一般情况下,锁并不可怕,只有遇到死锁时比较麻烦。
select * from
v$locked_object;
可以查到系统中被锁住的对象。
再和 select * from v$session
中连接,查出是锁标的session;
alter system kill session
'sid,serial' 即可
在ops下,更麻烦一点
需要查询的动态试图要加‘G’,例如gv$session
同时,在kill
session时需要找到改会话所在的实例,连接到正确的instance中kill才会成功
<详细步骤>
查询表的状况的对象:V$LOCK,
V$LOCKED_OBJECT, V$SESSION, V$SQLAREA, V$PROCESS
select * from
v$locked_object
select * from
dba_objects
方法:
首先查看那些表被锁住了
-----------------------------------------------------------------
select b.owner,
b.object_name, a.session_id, a.locked_mode
from v$locked_object a,
dba_objects b
where b.object_id =
a.object_id;
-----------------------------------------------------------------
select b.username,
a.LOCKED_MODE, b.sid, b.serial#, logon_time
from v$locked_object a,
v$session b
where a.session_id =
b.sid
order by
b.logon_time;
-----------------------------------------------------------------
select b.sid,
b.serial#,
c.object_name,
b.username,
a.LOCKED_MODE,
b.logon_time
from v$locked_object a,
v$session b, dba_objects c
where a.session_id =
b.sid
and a.object_id =
c.object_id
order by
b.logon_time;
-----------------------------------------------------------------
杀进程中的会话
alter system kill session
'SID,SERIAL#';
例如:
alter system kill session
'29,5497';
------------------------------------------------
数据库中其他知识补充:
ORACLE里锁有以下几种模式:
0:none
1:null 空
2:Row-S
行共享(RS):共享表锁
3:Row-X
行专用(RX):用于行的修改
4:Share
共享锁(S):阻止其他DML操作
5:S/Row-X
共享行专用(SRX):阻止其他事务操作
6:exclusive
专用(X):独立访问使用
数字越大锁级别越高,
影响的操作越多。
一般的查询语句如select ... from ...
;是小于2的锁, 有时会在v$locked_object出现。
select ... from ... for
update; 是2的锁。
当对话使用for
update子串打开一个游标时,
所有返回集中的数据行都将处于行级(Row-X)独占式锁定,
其他对象只能查询这些数据行,不能进行update、delete或select...for
update操作。
insert / update / delete ...
; 是3的锁。
没有commit之前插入同样的一条记录会没有反应,
因为后一个3的锁会一直等待上一个3的锁,
我们必须释放掉上一个才能继续工作。
创建索引的时候也会产生3,4级别的锁。
locked_mode为2,3,4不影响DML(insert,delete,update,select)操作,
但DDL(alter,drop等)操作会提示ora-00054错误。
有主外键约束时 update / delete ... ;
可能会产生4,5的锁。
DDL语句时是6的锁。
SELECT S.SID
SESSION_ID,
S.USERNAME,
s.SERIAL#,
DECODE(LMODE,
0,
'None',
1,
'Null',
2,
'Row-S (SS)',
3,
'Row-X (SX)',
4,
'Share',
5,
'S/Row-X (SSX)',
6,
'Exclusive',
TO_CHAR(LMODE))
MODE_HELD,
DECODE(REQUEST,
0,
'None',
1,
'Null',
2,
'Row-S (SS)',
3,
'Row-X (SX)',
4,
'Share',
5,
'S/Row-X (SSX)',
6,
'Exclusive',
TO_CHAR(REQUEST))
MODE_REQUESTED,
O.OWNER || '.' ||
O.OBJECT_NAME || ' (' || O.OBJECT_TYPE || ')',
S.TYPE
LOCK_TYPE,
L.ID1 LOCK_ID1,
L.ID2 LOCK_ID2
FROM V$LOCK L,
SYS.DBA_OBJECTS O, V$SESSION S
WHERE L.SID =
S.SID
AND L.ID1 =
O.OBJECT_ID;