在介绍oracle的锁之前,先介绍一下什么叫阻塞,这个相信大家都遇到过。阻塞和死锁是两回事,这个可能会经常混淆。
阻塞:
一个session持有一定的资源,但是其他session也要持有这个资源,那么这时就会阻塞,请求的session就会一直等待,直到持有资源的session释放该资源。
常见的产生阻塞的情况:INSERT、UPDATE、DELETE、MERGE和SELECT FOR UPDATE这些都会产生阻塞
insert一般是在有主键的情况下,拆入相同的值,就会产生阻塞,直到提交或者回滚,另一个回话会返回一个错误,比如表中常用的ID字段,所以这里大家都使用sequence,这样就可以避免。
Merge、Update和Delete这些类似,比如你正在更新别人更新的行,你只能等待,如果别人的更新很大,那么你只能一直等待再等待
这里只是简单介绍,不再深入
死锁:
这个还是举例好理解:有t1和t2两张表,每个表里都有一条记录。
那么在session1中更新t1,在session2中更新t2
再在session2中更新t1,这时只能叫阻塞,如果再在session1中更新t2,就死锁了。
下面开始介绍oracle 锁的种类:
⊙ DML锁
⊙ DDL锁
⊙ 内部锁或LATCH
LATCH这里先不介绍,它是内部锁,主要是涉及到内存组件的。
DML锁:
上面介绍的阻塞,其实就是产生了相关锁,而且注意select也是DML,但是他不产生锁,所以在你select的时候,是可以drop的,以及其他操作。DML锁的作用就是事物在修改期间,另一个session不能进行修改,那么DDL那就更不行了。
oracle又将DML拆分为两种锁:
⊙ 表级锁 TM(表对象上)
⊙ 行级锁 TX(行对象上)
这里表好比一幢楼房,行好比就是住户,你自己的家门有锁,每个单元下面还有个大门,也会锁,那大家回家的时候肯定先的进大门,然后再开自己家的。那么这样其实对大的并发的是会有影响的,因为要进自己家门,必须的走大门开锁,所以对于大并发系统,现在有一种数据库,nosql,是以键-值的形式存在,也不会像oracle有表结构,它是自由模式的,简单查询,这个在并发的效率上是比oracle高,但是事物的一致性不高。
这里表级锁又分7类:
0号锁:也就是select,不会锁资源
每个dml语句操作行都会有一个TX锁,
DML语句和select for update既触发行级锁又触发表级锁
一个事物只能得到一个TX锁,但是TM锁和你DML语句涉及到的对象的个数对应。
DML_LOCKS这个参数是可以控制这个TM锁的个数,如果设置为0的话,就是禁用了DDL操作,不用担心DDL操作对表结构的改变。
表级锁控制图:
表行级控制图:
1号锁,null,系统自动生成的锁,比如数据字典,你删除一张表,那么肯定系统肯定会修改相关数据字典。所以你drop表,要通知持有该锁的session,这个锁很难理解,因为是内部锁。
2号锁,SS,看上图,和x锁冲突,如果持有了2号锁,那么肯定不能持有6号锁。比如select for update就会持有2号锁
看上面行级控制图,SS锁会和行级别SX,和SS锁在处理相同行的时候会有堵塞
LOCK TABLE table IN ROW SHARE MODE;==显式产生RS锁,也就是2号锁,2号锁和表级别的锁,除了X锁,都兼容。
3号锁,SX,不会和1,2,3号锁冲突,但是在行级别可能和2,3号冲突。oracle的dml会产生这个锁,下面例子:
SQL> create table t1 (a int primary key);
Table created.
SQL> create table t2 (b int references t1);
Table created.
SQL> insert into t1 values(1);
1 row created.
SQL> insert into t1 values(2);
1 row created.
SQL> commit;
Commit complete.
SQL> update t1 set a=5 where a=1;
1 row updated.
SQL2> select * from v$lock where sid=138;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000EF71DDA8 00000000EF71DDD0 138 TM 22673 0 3 0 264 0
00000000F0B11F48 00000000F0B11F80 138 TX 655370 2575 6 0 264 0X
更新记录有行级排它锁,也就是看到的6号锁,TX锁,而且还会有TM表级锁,这里可以看到是3号锁,也就是SX,
SQL2> SELECT OBJECT_NAME,L.LOCKED_MODE FROM V$LOCKED_OBJECT L,DBA_OBJECTS O WHERE L.SESSION_ID=138 AND L.OBJECT_ID=O.OBJECT_ID;
OBJECT_NAME LOCKED_MODE
-------------------------------------------------------------------------------------------------------------------------------- -----------
T1 3
这里可以查看锁定的对象还有锁的模式,3号SX。
由于上面在更新a=1的行为5,所以在插入的时候,肯定会等待,阻塞。
insert into t1 values(1);---阻塞
insert into t1 values(5);--阻塞
select * from t1 where a=1 for update;--阻塞,
select * from t1 for update;--阻塞,这里就验证了可能和2,3级别的锁冲突,如果是插入别的值或者查询其他行,不会阻塞。
4号锁:S 叫共享锁,也叫只读锁。
上面图示可以看出,S和带有X的锁都冲突,这里要注意select for update10g以后升级为了SX锁,这就以为着也冲突。举例:
SQL1> lock table t1 in share mode;
Table(s) Locked.
SQL2> select * from charge.t1 where a=1 for update;
一直在等待。
顺别再介绍下6号:X
看图:只和1号兼容,其他都冲突,行锁只有TX有效,一定要记住DML和select for update都会产生行锁,有TX锁的,肯定都有表锁。
今天暂时先介绍到这里,续集继续。