0%

MySQL锁机制

文章字数:1042,阅读全文大约需要4分钟

锁分类

按照粒度可以分为表级锁table-level locking和行级锁row-level locking

  • 表级锁:开销小,加锁快。但是因为锁定的粒度大,发生冲突的概率高,支持并发度低。适合查询为主的应用

  • 行级锁:开销大,加锁慢。但是粒度小,发生冲突概率低,支持并发高。

InnoDB默认采用行级锁MyISAMMEMORY默认采用表级锁

行锁

InnoDB实现类两种类型的行锁

  • 共享锁S:获取该锁的事务可以读取数据,并同时允许其他事务获取改行的共享锁,但阻止其他事务获取排他锁。

  • 排他锁X:获取该锁的事务可以更新或删除数据行,同时阻止其他事务获取该行的共享锁和排他锁。

锁类型 共享锁S 排他锁X
共享锁S 兼容 冲突
排他锁X 冲突 冲突

手动添加行锁

默认情况下锁都是自动获取的,但也可以手动加锁。

  • select * from table where id = 1 for share
    for share就是加共享锁,MySQL8.0之前的版本可以使用select...lock in share mode
    由于 InnoDB 中的自动提交 autocommit 默认设置为 ON,我们必须在事务中为数据行加锁;或者将 autocommit 设置为 OFF。

  • select * from table where id = 1 for update
    for update是获取排他锁
    数据行被其它事务加了共享锁,并且事务未结束(即未释放)此时其它事务加排他锁则会处于等待状态,直到超时。(因为不兼容)

意向锁

为了兼容表级锁和行级锁,InnoDB采用了意向锁(属于表级锁)。意向锁为自动添加,也可以手动LOCK TABLE添加

  • 意向共享锁(IS):事务在给数据行加行级共享锁之前,必须先取得该表的 IS 锁。
  • 意向排他锁(IX):事务在给数据行加行级排他锁之前,必须先取得该表的 IX 锁。
锁类型 共享锁S 排他锁X 意向共享锁IS 意向排他锁
共享锁S 兼容 冲突 兼容 冲突
排他锁X 冲突 冲突 冲突 冲突
意向共享锁IS 兼容 冲突 兼容 兼容
意向排他锁IX 冲突 冲突 兼容 兼容

意向锁只是标记当前有事务在操作行级锁,意向锁意向锁之间并不会冲突

手动添加意向锁

  • select * from t where id = 1 for update 添加行锁会自动添加表锁
  • lock tables t read 也可以手动添加
  • unlock tables 释放表上的排他锁

行锁实现

  1. 记录锁Record Lock:通过索引值进行加锁

  2. 间隙锁Gap LockBETWEEN 1 and 10这样的语句会产生多行记录的锁,此时就是间隙锁。代表一段区域,可以是两个索引之间、某个索引之前、某个索引之后。

  3. Next-key锁:该锁可以锁住当前位置和之前的区域,即记录锁+间隙锁。主要用于解决幻读,使用for update时通过加Next-key解决幻读。普通情况下采用MVCC解决幻读

可以使用SHOW ENGINE INNODB STATUS命令查看InnoDB监控中关于锁的事务数据
记录锁永远都是锁定索引记录,优先聚集索引,没有定义索引InnoDB会自动创建隐藏的聚集索引。