问题引入:
oracle使用中,碰到几次奇怪的现象,就是一个简单的过程或者语句,执行奇慢,第一感觉就是相关事务被blocked。
背景知识:
orcle使用锁来保证数据的一致性。一般死锁,不需要我们关心,因为,oracle会自动检测死锁,并回滚其中一个事务。
锁的参看方法:可以通过字典v$lockv,$locked_object来查看,其中更多的关联信息需要参考字典v$sessionv,$objects
v$lockv lists the locks currently held by the Oracle database server and outstanding requests for a lock or latch.
oracle的锁分为DML锁和DDL锁两类,DML锁根据对象分为两大类,行锁(TX)和表锁(TM),
行锁就一种exclusive(6),因为正常一个行是没有锁的,如果你要修改,就需要在这个行上加一个锁(6),防止其他事务使用之。
表锁的分类主要是根据行的操作情况来分类的,分为:
0 - none
1 - null (NULL)
2 - row-S (SS) 行共享表锁,表明这个表有行正在查询,主要是select for update of 语句需要使用
3 - row-X (SX) 行排他表锁,表明这个表有行正在被修改等,主要是 insert/delete/insert等语句使用
4 - share (S) 共享表锁, 应用开发不常出现,主要是oracle内部使用或者,通过手工 lock table实现
5 - S/Row-X (SSX) 行共享排他表锁,同上
6 - exclusive (X) 排他表锁 同上
可见实际使用中,和应用开发紧密相关的也就是TX-2和TX-3
DML访问的时候,要首先获取一个表锁TM,然后再根据具体的语句获取相关的TX锁,如果任何一个锁获取失败都会导致相关的进程阻塞。
例子:
1、在13#会话,select * from member t where id=1 for update;
2、然后,使用另一个连接
SQL>select * from v$lock where sid>10;
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
6FB8948C 6FB89598 13 TX 65572 12983 6 0 40 0
6FB4E074 6FB4E088 13 TM 29882 0 2 0 40 0
表明,
导致这个锁的会话是13#,通过v$session可参考这个会话的信息
这个DML获得了TM-2(SS)和TX-6锁,
到现在位置已经获取了40s,
且没有导致其他事务阻塞。
其中,TM锁的对象ID是29882,通过user_objects字典可以找到这个实际上就是一个表
SQL> select * from v$locked_object;
XIDUSN XIDSLOT XIDSQN OBJECT_ID SESSION_ID ORACLE_USERNAME OS_USER_NAME PROCESS LOCKED_MODE
---------- ---------- ---------- ---------- ---------- ------------------------------ ------------------------------ ------------ -----------
1 36 12983 29882 13 LIUFEI GCLEARliufeicc 3412:3480 2
表明,这个时候锁住了29882,
实际的 TX-6 大概由于不是一个DB对象,也就没有在 v$locked_object
3、在开一个会话(10#) delete from member t where t.id=1;这个会话就会被阻塞,语句无法执行下去
再回到中间的那个连接,
SQL> select * from v$lock where sid>9;
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
6FB4E0F8 6FB4E10C 10 TM 29882 0 3 0 130 0
702BDCAC 702BDCBC 10 TX 65572 12983 0 6 130 0
6FB8948C 6FB89598 13 TX 65572 12983 6 0 722 1
6FB4E074 6FB4E088 13 TM 29882 0 2 0 722 0
可见
10#首先获得了29882上的TM3的锁
但是,由于记录(65572,12983)被13#上了一个TX-6,10#的操作虽然也想获取这个一个锁,就无法获取到,就被阻塞了。
rollback之后,再 delete from member t where t.id=2;这个会话,就不会被阻塞了,语句正常执行,因此他要对id=2的记录上TX-6[@more@]