一 锁分类(按粒度分)
解决并发、数据安全的问题,用锁。
(1)表级锁
粒度最大,对整表加锁,实现简单 ,资源消耗也比较少,加锁快,不会出现死锁 。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。
(2)行级锁
粒度最小。 减少数据库冲突。加锁粒度最小,并发度高,加锁开销最大,加锁慢,会出现死锁。 InnoDB支持的行级锁:
1)行锁 Record Lock: 对索引项加锁,锁定符合条件的行。其他事务不能修改和删除加锁项;
2)间隙锁 Gap Lock: 对索引项之间的“间隙”加锁,锁定记录的范围(对第一条记录前的间隙或最后一条将记录后的间隙加锁),不包含索引项本身。其他事务不能在锁范围内插入数据,这样就防止了别的事务新增幻影行。
3)行锁和间隙锁组合 Next-key Lock: 锁定索引项本身和索引范围。解决幻读问题。
虽行级索粒度小、并发度高等特点,但表级锁有时候非常必要:
事务更新大表中的大部分数据直接使用表级锁效率更高;用行级索很可能引起死锁导致回滚。
二、另外两个表级锁:IS和IX
当一个事务需要给自己需要的某个资源加锁的时候,如果遇到一个共享锁正锁定着自己需要的资源的时候,自己可以再加一个共享锁,不过不能加排他锁。但是,如果遇到自己需要锁定的资源已经被一个排他锁占有之后,则只能等待该锁定释放资源之后自己才能获取锁定资源并添加自己的锁定。而意向锁的作用就是当一个事务在需要获取资源锁定的时候,如果遇到自己需要的资源已经被排他锁占用的时候,该事务可以需要锁定行的表上面添加一个合适的意向锁。如果自己需要一个共享锁,那么就在表上面添加一个意向共享锁。而如果自己需要的是某行(或者某些行)上面添加一个排他锁的话,则先在表上面添加一个意向排他锁。意向共享锁可以同时并存多个,但是意向排他锁同时只能有一个存在。
InnoDB另外的两个表级锁:
意向共享锁(IS): 事务准备给数据行记入共享锁,事务在一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX): 事务准备给数据行加入排他锁,事务在一个数据行加排他锁前必须先取得该表的IX锁。
注意:
这里的意向锁是表级锁,表示的是一种意向,仅仅表示事务正在读或写某一行记录,在真正加行锁时才会判断是否冲突。意向锁是InnoDB自动加的,不需要用户干预。
IX,IS是表级锁,不会和行级的X,S锁发生冲突,只会和表级的X,S发生冲突。
InnoDB的锁机制兼容情况如下:
三 死锁和避免死锁
InnoDB的行级锁是基于索引实现的,如果查询语句为命中任何索引,用表级锁. 对索引加的锁,不针对数据记录,访问不同行记录,如用相同索引键仍锁冲突,
SELECT...LOCKINSHARE MODE 或 SELECT...FORUPDATE;
用锁时,如没有定义索引,InnoDB创建隐藏聚簇索引加记录锁。
InnoDB锁逐步获得,两个事务都要获得对方持有的锁,都等待,产生死锁。 可检测到,并使一个事务释放锁回退,另一个获取锁完成事务,避免死锁:
(1)表级锁来减少死锁
(2)多个程序尽量相同顺序访问表(解决并发理论中哲学家就餐问题一种思路)
(3)同一个事务尽可能一次锁定所有资源。
四、总结与补充
页级锁: 介于行级锁和表级锁中间。表级锁速度快,但冲突多,行级冲突少,但速度慢。页级折衷,一次锁定相邻一组记录。BDB支持页级锁。开销和加锁时间界于表锁和行锁之间,会出现死锁。并发度一般。