数据库锁

2020-09-11  本文已影响0人  小幸运Q

https://www.cnblogs.com/liuqing576598117/p/10366233.html


查看正在锁的事物:

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS

查看等待锁的事物:

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS

show processlist 查询表被锁进程


(1)共享锁(读保护,读的时候不能写)

T1: select * from table (执行N久)
T2: update table set column1='hello' 

过程:

T1运行 (加共享锁)
T2运行
If T1 还没执行完
  T2等......
else
  锁被释放
  T2执行
endif

T2之所以要等,是因为T2在执行update前,试图对table表加一个排他锁,而数据库规定同一资源上不能同时共存共享锁和排他锁。所以T2必须等T1。

(2)更新锁(Update lock)(只锁更新,写锁)

T1: select * from table(updlock) (加更新锁)
update table set column1='hello'
T2: select * from table(updlock)
update table set column1='world'
T3: select * from table

T1执行select,加更新锁。
T2运行,读的时候准备加更新锁,但发现已经有一个更新锁在那儿了,只好等T1更新完再select。
T3无影响直接读。

(3)排他锁(独占锁,Exclusive Locks)

T1: update table set column1='hello' where id<1000
T2: update table set column1='world' where id>1000

假设T1先达,T2随后至,这个过程中T1会对id<1000的记录施加排他锁.但不会阻塞T2的update,因为位置相互独立。

(4)意向锁(Intent Locks)

T1: select * from table (xlock) where id=10 --意思是对id=10这一行强加排他锁
T2: select * from table (tablock) --意思是要加表级锁

假设T1先执行,T2后执行,T2执行时,欲加表锁,为判断是否可以加表锁,数据库系统要逐条判断table表每行记录是否已有排他锁,如果发现其中一行已经有排他锁了,就不允许再加表锁了。只是这样逐条判断效率太低了。

实际上,数据库系统不是这样工作的。当T1的select执行时,系统对表table的id=10的这一行加了排他锁,还同时悄悄的对整个表加了意向排他锁(IX),当T2执行表锁时,只需要看到这个表已经有意向排他锁存在,就直接等待,而不需要逐条检查资源了。

(5)计划锁(Schema Locks)

alter table..(加schema locks,称之为Schema modification (Sch-M) locks)

DDL语句都会加Sch-M锁,该锁不允许任何其它session连接该表。连都连不了这个表了,当然更不用说想对该表执行什么sql语句了。

(6) 间隙锁

锁范围,阻止在区间插入新的数据,防止幻读。往往针对非唯一索引。

触发条件:范围查询并且查询未命中记录,查询条件必须命中索引、间隙锁只会出现在REPEATABLE_READ(重复读)的事务级别中。

(7) 临键锁

总结来说它就是记录锁和间隙锁的组合,临键锁会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间也会锁住,再之它会把相邻的下一个区间也会锁住。

触发条件:范围查询并命中,查询命中了索引。


可以强制某个事务回滚,释放掉锁。

举例:死锁发生的场景

事务A 事务B
delete from T1 where id=1  
  update T2 set xxx where id=5
update T2 set where id=5  
  delete from T1 where id=1
commit commit
上一篇下一篇

猜你喜欢

热点阅读