为了解决数据库被并发事物访问所带来的问题,数据库提供了锁机制来应对。数据库锁根据锁定的对象不同,可以分为表级锁和行级锁,表级锁锁定的对象是整张表,行级锁锁定的对象是特定的数据行;根据锁之间的关系可以分为共享锁和独占锁,共享锁允许其他事物获取共享锁,但是不予许其他事物获取独占锁。独占锁既不允许其他事物获取共享锁,又不允许其他事物获取独占锁。
行级锁:insert 、update、 delte 和 select…for update等都会隐士的获取一个行级锁。
表级锁:lock table tableName in shre mode 或 lock tabletableName in exclusive mode的获取一个表级锁。
共享锁:共享锁只支持表级锁,没有行级别的。通过lock table tableName in shre mode 添加。
独占锁:所有的行级锁都是独占锁。Lock table tableName inexlusive mode对整张表获取独占锁。
共享锁的行为:每个事物的共享锁都防止其他事物的独占锁,但是自己的共享锁不妨自己的独占锁。如果事物A独自获取了表T的共享锁,那么事物A还可以获取表T上的独占锁;如果事物A获取了表T的共享锁,事物B也获取了表T的共享锁,那么此时事物A不能获取T的独占锁了,因为事物B的共享锁不允许。
事物A:locktable tt_stu insharemode;
事物A进行如下操作会成功:insertinto tt_stu values(4,'a')
deletefrom tt_stu whereid=3;
update tt_stu setname='llll0l'whereid=1;
SELECT * FROM tt_stu whereid=2forupdate;
这四个操作都需要独占锁,因为只有自己持有共享锁,同一个事物的共享锁允许自己的独占锁。反过来自己的独占锁也不会排斥自己的共享锁,也就是自己不排斥自己。
如果上述情况,事物A在进行增删改查之前,事物B也执行了locktable tt_stu insharemode;则后四个操作会被阻塞,直到事物B提交了事物释放了共享锁。
如果上述情况,事物A执行了insert语句,则此时事物B去执行locktable tt_stu insharemode;事物B会被阻塞,因为事物A不仅有表上的共享锁,insert会隐式添加一个独占锁,阻止了事物B的共享锁。
独占锁的行为:每个事物的独占锁,都防止其他事物的共享锁和独占锁,允许自身事物的共享锁和独占锁。
事物A:locktable tt_stu inexclusivemode;
事物A进行如下操作都会成功:insertinto tt_stu values(4,'a');
deletefrom tt_stu whereid=2;
update tt_stu setname='llll0l'whereid=2 ;
SELECT * FROM tt_stu whereid=2forupdate;
locktable tt_stu insharemode;
因为他们在同一个事物,所以没影响。
行级独占锁和表级独占锁有区别:事物A执行:locktable tt_stu inexclusivemode;这是表独占锁,事物B无法获取该表的共享锁、及任意行的独占锁(也就是意味事物B无法进行增、删、改以及select…for update)。
如果事物A执行:SELECT * FROM tt_stu whereid=2forupdate;仅仅对id=2的数据行添加锁,事物B无法对id=2的数据行添加独占锁以及不能添加共享锁(因为共享锁只能是表级锁,包括id=2的行),但是事物B可以对其他数据行添加独占锁(可以对其他数据行进行修改删除以及执行insert)。
如果事物A执行:insertinto tt_stu values(4,'a');对id=4的数据行获取独占锁,事物B无法获取共享锁以及表独占锁(不可以执行locktable tt_stu insharemode和locktable tt_stu inexclusivemode),但是可以执行任意行独占锁(可以执行任意行insert、update、delte和select for update )。
PS: 普通的select语句无视锁的存在,锁对其没限制。
Oracle的5种表级锁:之前已经使用过了2种表级锁,表共享锁和表独占锁,以及行共享表级锁、行独占表级锁和表共享行独占表级锁。下图给出了表锁与表锁、dml、ddl的关系。
关系图(此处dml仅指增删改及select for update)
本文暂时没有评论,来添加一个吧(●'◡'●)