为什么 MySQL InnoDB 也为 update/delete 操作获取 Gap 锁?
Why MySQL InnoDB also acquire Gap locks for update/delete operation?
据我所知gap lock是用来防止幻读的,我通过Google搜索发现gap lock在大多数文章中都是通过locking read设置的。
A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record. For example, SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; prevents other transactions from inserting a value of 15 into column t.c1, whether or not there was already any such value in the column, because the gaps between all existing values in the range are locked.
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-gap-locks
我想这(在锁定读取时设置间隙锁)就足够了。为什么update,delete也设置gap lock.
UPDATE ... WHERE ... sets an exclusive next-key lock on every record the search encounters. However, only an index record lock is required for statements that lock rows using a unique index to search for a unique row.
https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html
另一个问题是如果没有可以附加间隙锁的 suitable 索引会发生什么?
回退锁定整个table?
这里我们假设使用默认的事务隔离级别Repeatable读取。
这取决于您的SELECT、UPDATE 或DELETE 中的条件。他们设置间隙锁以防止其他并发会话向集合中添加符合条件的行。
在 InnoDB 中,锁定语句总是锁定最新提交的行版本。所以他们并没有真正遵守 REPEATABLE READ 快照。他们的行为更像是 READ-COMMITTED。
因此,如果你做这样的声明:
UPDATE FROM MyTable SET ... WHERE created_at > '2020-03-22';
它必须锁定最高值 created_at 之后的间隙,这将防止其他会话添加新行。
这是为了模拟可重复读取,以确保如果您再次运行相同的更新,它将影响相同的行,并且不会意外影响新行。
据我所知gap lock是用来防止幻读的,我通过Google搜索发现gap lock在大多数文章中都是通过locking read设置的。
A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record. For example, SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; prevents other transactions from inserting a value of 15 into column t.c1, whether or not there was already any such value in the column, because the gaps between all existing values in the range are locked.
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-gap-locks
我想这(在锁定读取时设置间隙锁)就足够了。为什么update,delete也设置gap lock.
UPDATE ... WHERE ... sets an exclusive next-key lock on every record the search encounters. However, only an index record lock is required for statements that lock rows using a unique index to search for a unique row.
https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html
另一个问题是如果没有可以附加间隙锁的 suitable 索引会发生什么? 回退锁定整个table?
这里我们假设使用默认的事务隔离级别Repeatable读取。
这取决于您的SELECT、UPDATE 或DELETE 中的条件。他们设置间隙锁以防止其他并发会话向集合中添加符合条件的行。
在 InnoDB 中,锁定语句总是锁定最新提交的行版本。所以他们并没有真正遵守 REPEATABLE READ 快照。他们的行为更像是 READ-COMMITTED。
因此,如果你做这样的声明:
UPDATE FROM MyTable SET ... WHERE created_at > '2020-03-22';
它必须锁定最高值 created_at 之后的间隙,这将防止其他会话添加新行。
这是为了模拟可重复读取,以确保如果您再次运行相同的更新,它将影响相同的行,并且不会意外影响新行。