Windows下Oracle表死锁处理过程
1.问题现象
Oracle 12c数据库安装在Windows下,在一个大数据量表批量更新操作时,异常中断。表锁死,查询访问长时间无反应。
2.处理过程
(1)锁表对象
select object_name as 对象名称, s.sid, s.serial#, p.spid as 系统进程号from v$locked_object i, dba_objects o, v$session s, v$process pwhere i.object_id = o.object_idand i.session_id = s.sidand s.paddr = p.addr;
查询锁表的对象,找到表名,关注对应的sid ,serial# ,spid 。
(2)在Oracle中杀进程
在数据库所属用户登录,杀会话进程。
alter system kill session 'sid,s.serial#';
例如:sid ,serial# 分别是16,6046
alter system kill session '16,6046';
提示成功,但是再次查询锁对象,依然存在。
增加参数,立刻执行生效
alter system kill session '16,6046' immediate;
提示:
ORA-00031: session marked for kill
(3)在Windows中杀进程
Windows 中没有kill命令,杀指定进程。在Windows中任务管理器,Oracle就是一个进程。
Oracle提供一个命令orakill :
用法: orakill sid thread
sid:是数据库实例名
thread:是锁对象的spid
查询数据库实例名:
select t.INSTANCE_NAME from v$instance t;
假设 实例名:orcl ,spid :10404
进入cmd命令行,执行:
orakill orcl 10404
结束锁死进程。
在Oracle中,查询不到对应的锁死表对象。
(4)清除数据
再查询锁死表,还是没有反映,应该是解锁了,可以查询迅速反馈结果了,但是与预期不同。
最终用truncate table 清除所有记录,重新导入数据,表终于可以查询返回结果了 。
3. Oracle锁的分类
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
Oracle的锁机制是一种轻量级的锁定机制,不是通过构建锁列表来进行数据的锁定管理,而是直接将锁作为数据块的属性,存储在数据块首部。
在 Oracle 数据库中,它并不是对某个表加上锁或者某几行加上锁, 锁是以数据块的一个属性存在的。 也就是说, 每个数据块本身就存储着自己数据块中数据的信息,这个地方叫 ITL( Interested Transaction List), 凡是在这个数据块上有活动的事务,它的信息就会记录在这里面供后续的操作查询,一保证事务的一致性。
(1)按用户和系统分类
-
自动锁( Automatic Locks)
当进行一项数据库操作时,缺省情况下,系统自动为此数据库操作获得所有有必要的锁。
自动锁分为三种:- DML 锁
- DDL 锁
- systemlocks。
-
手动数据锁( Manual Data Locks)
某些情况下,需要用户锁定数据库操作要用到的数据,才能使数据库操作执行得更好,显式锁是用户为数据库对象设定的,执行命令锁表:
lock table table_name;
(2)按锁级别分类
可分为:排他锁(exclusive lock,即X锁)和共享锁(share lock,即S锁)
-
排他锁(exclusive lock,即X锁)
事务设置排它锁后,该事务单独获得此资源,另一事务不能在此事务提交之前获得相同对象的共享锁或排它锁。 -
共享锁(share lock,即S锁)
共享锁使一个事务对特定数据库资源进行共享访问——另一事务也可对此资源进行访问或获得相同共享锁。
共享锁为事务提供高并发性。
(3)按操作分类
DML锁
DML 锁用于控制并发事务中的数据操纵,保证数据的一致性和完整性。
DML锁主要用于保护并发情况下的数据完整性。
DML 语句能够自动地获得所需的表级锁(TM)与行级(事务)锁(TX)。
它又分为:
( 1) TM 锁(表级锁)
( 2) TX 锁( 事务锁或行级锁)
当 Oracle 执行 DML 语句时,系统自动在所要操作的表上申请 TM 类型的锁。当 TM 锁获得后,系统再自动申请 TX 类型的锁,并将实际锁定的数据行的锁标志位进行置位。
这样在事务加锁前检查 TX锁相容性时就不用再逐行检查锁标志,而只需检查 TM 锁模式的相容性即可,大大提高了系统的效率。
在数据行上只有 X 锁(排他锁)。
在 Oracle 数据库中,当一个事务首次发起一个 DML 语句时就获得一个 TX 锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行 DML 语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后, TX 锁被释放,其他会话才可以加锁。
当 Oracle 数据库发生 TX 锁等待时,如果不及时处理常常会引起 Oracle 数据库挂起,或导致死锁的发生,产生ORA-600 的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。
(4)锁等级
- 行锁:0、6两类锁
- 表锁:0、1、2、3、4、5、6七类锁
- 0(none)
- 1(null)
- 2(RS)
- 3(RX)
- 4(S)
- 5(SRX)
- 6(X)
R是ROW行,S是SHARE共享,X是eXclusive排他,独占锁的意思。
0:null 空
一般的SELECT,在表和行上都是0级锁
1:null 空
1级锁有:Select有时会在v$locked_object出现。
2:Row-S 行共享(RS):共享表锁,sub share
2级锁有:Lock Row Share,create index online
表锁的情况下:
locked_mode 2不影响后一个locked_mode 2、3、4、5的会话,如果后一个会话locked_mode为6,则后一个会话操作会提示ora-00054错误。
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
行锁的情况下:
locked_mode 2对应行锁0级锁,不影响其他会话。
3:Row-X 行独占(RX):用于行的修改,sub exclusive
3级锁有:Insert, Update, Delete, Select for update,Lock Row Exclusive
表锁的情况下:
locked_mode 3不影响后一个locked_mode 3的会话,但如果后一个会话locked_mode为4,5,6,则后一个会话操作会提示ora-00054错误。
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
行锁的情况下:
locked_mode 3的表锁对应行锁6级锁,两个会话对同一行则影响。
4:Share 共享锁(S):阻止其他DML操作,share
4级锁有:Create Index, Lock Share
5:S/Row-X 共享行独占(SRX):阻止其他事务操作,share/sub exclusive
5级锁有:Lock Share Row Exclusive
具体来讲有主外键约束时update/delete … ; 可能会产生4,5的锁。
6:exclusive 独占(X):独立访问使用,exclusive
6级锁有:Drop table, Drop Index, Alter table,Truncate table, Lock Exclusive。