1.各类锁兼容性
参考于https://www.cnblogs.com/leohahah/p/8465062.html,这里只理清楚了部分我理解的。
2.部分锁的理解
框架稳定锁
数据库在编译和执行查询时使用SCH-S锁,但是无法执行获取该锁的并发DDL操作和并发DML操作。
框架修改锁
数据库在执行DDL操作时使用该锁,在该锁释放之前,阻止该表外围的所有并发操作。
共享锁
1.说明
T1: select * from table (请想象它需要执行1个小时之久,后面的sql语句请都这么想象)
T2:
update table set column1='hello'
2.过程
T1运行 (加共享锁)
T2运行
If T1
还没执行完
T2等......
else
锁被释放
T2执行
endif
更新锁
1.说明
更新锁只作用于行。
2.过程
图1
右侧窗口未加更新锁,在读一行数据的时间很短,所以对该行的共享锁(S锁)的排队时间可以忽略不计,可以认为有窗口无锁。左窗口第一句查询使用了更新锁(U锁),紧接着更新该行资源,更新锁升级为排他锁(X锁)。前5秒,右侧窗口可以查出更新之前的数据,如图1,接着查出更新之后的数据,如图2。
图2
图3
如果给右侧语句也加上更新锁(U锁),则右侧窗口的结果会在左侧事务提交后执行,从图3 两个窗口的执行时间上可以看到。PS:因为没办法两个窗口完全同时执行语句,所以右侧时间会短一些。
排他锁
使用排他锁(X 锁)时,任何其他事务都无法修改数据;仅在使用 NOLOCK 提示或未提交读隔离级别时才会进行读取操作。
DML操作虽然是读取和修改的合并,但是只有update才会先加IU、U锁来读取数据,然后修改时转化为IX、X。而删除和插入我们可以认为从一开始就是加的IX、X锁。另外,UPDATE 语句可能根据与一个表的联接修改另一个表中的行。 在此情况下,除了请求更新行上的排他锁之外,UPDATE 语句还将请求在联接表中读取的行上的共享锁(S锁)。
图4
图4的执行时间上可以看到在排他锁(X锁)在释放之前,共享锁(S锁)处于等待状态,这时候查询语句需要加上NOLOCK
意向锁
官方描述:数据库引擎使用意向锁来保护锁层次结构的底层资源,以防止其他事务对自己锁住的资源造成伤害,提高锁冲突检测性能。
1.提高锁冲突检测性能:当我们删除A表中id=1000的数据时,会给id=1000的数据加上X锁,这时如果有其他事务要求更新整张表数据,就会先找该表中是否有S锁。这时如果表主键是自增长,则需要消耗999次时间资源,找到id=1000的数据,然后不允许挂S锁。
这时出现了意向锁,当给id=1000的行数据挂上X锁时,会为Page和Object表上挂意向排他锁(IX锁),IX锁和S锁冲突,直接返回结果。
2. 保护锁层次结构:当查询A表某页数据时,理想情况下,同时有用户删除整个表数据,这时,虽然查询在前,但是查出的数据是被删除后的结果。而在有意向共享锁(IS锁)的情况下,数据库引擎先对表挂上IS锁,由于IS锁和X锁冲突,这样避免了数据错误。
共享意向排他锁
如图5所示,在当前数据页挂上了共享意向排他锁。意味当前页与S锁、U锁和X锁冲突,当前页所在表挂上了IX锁,当前表可以挂IS锁,但不允许挂S锁、U锁和X锁及其意向锁。
图5
共享意向更新锁
图6
如图6,page同时拥有了S锁和IX锁,在高并发时,该页在某时刻允许查询,但不允许更新。但在此时,Page挂上了SIX锁,但是表挂上的时IX锁,这时候查询,会给表上挂IS锁,不会和IX锁冲突,但是Page上的IX锁会和S锁冲突,所以Page上S锁的状态时wait,此时查询需等待表上该行数据的X锁释放。