mysql

每种sql使用的锁类型

2019-02-28  本文已影响17人  骁兵

  锁定读、update和delete通常会在sql运行时,对扫描到的行设置记录锁,而不管where语句是否匹配该行,锁通常是Next-Key锁(记录锁+间隙锁),以防止其他事务在记录索引之前插入数据。

  如果查询使用二级索引,InnoDB会获取相应的聚簇索引并对其加锁。

  如果查询中没有索引,Mysql必须扫描全表,表中的每一行都将被锁,以防止其他事务插入数据。

  1. 唯一索引:只使用记录锁,没有间隙锁
  2. 范围搜索:使用间隙锁或next-key锁

  如果发生重复键错误,一个共享记录锁将被设置在重复键上,当其他事务拥有了这个键的排它锁时,这个共享锁可能会导致死锁。比如:

CREATE TABLE t1 (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

  假设有三个事务按以下顺序执行
Session 1:

START TRANSACTION;
INSERT INTO t1 VALUES(1);

Session 2:

START TRANSACTION;
INSERT INTO t1 VALUES(1);

Session 3:

START TRANSACTION;
INSERT INTO t1 VALUES(1);

Session 1:

ROLLBACK;

  事务1获取一个排它锁在新添加的行上,事务2和3会发生重复键错误,并都请求获取一个新行的共享锁,等到事务1回退,它释放排它锁,然后事务2和3都获取到共享锁,接着事务2和事务3会请求排它锁,但因为他们都拥有共享锁,这时会发生死锁,它们任何一个都无法获取排它锁。
  假设数据库已经包含了新添加的key为1的行,三个事务执行以下操作
Session 1:

START TRANSACTION;
DELETE FROM t1 WHERE i = 1;

Session 2:

START TRANSACTION;
INSERT INTO t1 VALUES(1);

Session 3:

START TRANSACTION;
INSERT INTO t1 VALUES(1);

Session 1:

COMMIT;

  事务1获取一个排它锁在要删除的行上,事务2和3会发生重复键错误,并都请求获取一个新行的共享锁,等到事务1提交后,它释放排它锁,然后事务2和3都获取到共享锁,接着事务2和事务3会请求排它锁,但因为他们都拥有共享锁,这时会发生死锁,它们任何一个都无法获取排它锁。

上一篇下一篇

猜你喜欢

热点阅读