14.2.2.6 Locks Set by Different SQL Statements in InnoDB

14.2.2.6 Locks Set by Different SQL Statements in InnoDB

锁定读,更新或者删除通常设置record locks 在每个index record,被扫描处理SQL语句。

不重要的是 是否有WHERE 条件在语句里 来排除记录。

InnoDB 不记住准确的WHERE 条件,但是只知道被扫描的索引范围。

locks 通常是 next-key locks 也堵塞inserts 到”gap” .

然而,gap locking可以被显示的关闭, 会导致next-key locking 不被使用

有关更多的信息,查看章节14.2.2.4, “InnoDB Record, Gap, and Next-Key Locks”. The transaction isolation level

also can affect which locks are set; see Section 13.3.6, “SET TRANSACTION Syntax”.

如果一个secondary index 被用于搜索和index record locks 设置是排它的,

InnoDB 也检索相应的clustered index records和加锁在上面。

共享锁和排它锁之间的差别在Section 14.2.2.1, “InnoDB Lock Modes”.描述

如果没有合适的索引对你的SQL语句,MySQL 必须扫描整个表来处理语句,

表的每个行都被锁住,从而阻止所有其他用户插入这个表。

重要的是创建一个好的索引,你的查询不必要扫描很多行。

对于 SELECT … FOR UPDATE or SELECT … LOCK IN SHARE MODE,

locks 被获得的行, 并被期望释放行不符合结果集标准的(比如, 如果它们不满足其中给出的标准).

然后,在某些情况下,记录可能不被立即锁定 因为关系在结果集和它的原始源是丢失了在查询执行期间。

比如, 在一个UNION, 被扫描的(被锁定的) 记录 可能被插入到一个临时表在评估是否它们符合结果集。

InnoDB 设置具体的锁类型如下:

1.SELECT … FROM 是一个一致性读, 读取一个数据库的快照 ,不设置锁除非事务隔离级别设置为SERIALIZABLE。

对于SERIALIZABLE level, 搜索设置共享的next-key locks 在index records.

2.SELECT … FROM … LOCK IN SHARE MODE 设置共享的 next-key locks 在所有的index records

3.搜索遇到的Index records, SELECT … FROM … FOR UPDATE 堵塞其他的会话

做 SELECT … FROM … LOCK IN SHARE MODE 或者 读某个事务隔离级别。

一致性读会忽略任何锁在记录上。

  1. UPDATE … WHERE .. 设置一个排它的next-key lock 在每个搜索的记录

5.DELETE FROM … WHERE … 设置一个排它的next-key lock 在每个搜索的记录

  1. INSERT 设置一个排它锁在插入的行,这个锁是一个Index-record 锁,

不是一个next-key lock(也就是说, 这个不是一个区间锁)

不妨碍其他会话插入gap 在行插入前

在插入该行之前, 一个区间锁叫做一个插入意向区间锁被设置,

这个锁发出信号意图是插入以这种方式,多个事务插入相同的index gap 不需要相互等待

如果它们不插入相同的位置在区间里。

假设有Index records 值为4和7, 单独的事务尝试插入值5和6 每个锁区间是4和7

插入意向锁优先的的到一个排它锁 在插入的行,但是不堵塞其他因为行是不冲突的。

如果发生重复的错误,一个共享的锁在重复的index record 被设置。共享锁的使用可能导致死锁

有多个会话尝试插入相同的数据 如果其他的会话已经有一个排它锁。

这个发生在另外的会话删除记录,假设一个InnoDB 表t1 有下面的结构;

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

现在假设有3个会话按顺序执行下面的操作:

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;

session 1的操作需要一个记录的排它锁, session 2的操作和session 3 导致重复的行错误发生

它们都需要请求一个共享锁对于这条记录。 当session 1回滚时, 它释放它的记录上的排它锁

session 2和session 3请求的共享锁被授予。在这个时间点,session 2和session 3死锁:

都不能获得排它锁对于记录 因为共享锁被其他人持有。

一个相似的请求发生 如果表已经包含一个记录 值为1 ,3个会话按顺序执行下面的操作:

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;

SESSION 1 的操作需要一个记录的排它锁, session 2和session 3的操作都导致 重复键错误

它们都需要一个记录的共享锁。 当session 1提交时,它释放它的排它锁,session 2和session 3请求的共享锁被授予。

INSERT … ON DUPLICATE KEY UPDATE 不同于一个单独的插入 一个排它的next-key lock 相比一个共享锁

REPLACE 像INSERT 一样 如果没有一个冲突在一个唯一键,否则, 一个排它的next-key lock 是防止在需要替换的记录上。

INSERT INTO T SELECT … FROM S WHERE … 设置一个排它index record lock(不是一个gap锁)

在每个插入T表的行。如果事务隔离级别是 READ COMMITTED,

或者 innodb_locks_unsafe_for_binlog 是启用的 且事务的隔离级别不是SERIALIZABLE,

InnoDB 不搜索 S表 作为一致读(没有锁).否则, InnoDB 设置共享的next-key locks 在S表的记录上。

InnoDB 可以随后设置locks

CREATE TABLE … SELECT … 执行SELECT 的共享的next-key locks或者作为一致读

当SELECT 是用于构成REPLACE INTO t SELECT .. FROM s WHERE … or UPDATE t … WHERE col IN (SELECT … FROM s

…), InnoDB 设置共享的next-key locks

当初始化一个先前指定的AUTO_INCREMENT 列,InnoDB 设置一个排它的锁在索引相关的尾部

在访问auto-increment 计数器,InnoDB 使用一个特定的 AUTO-INC 表lock 模式

当lock 持续 知道当前SQL语句的尾部,

不是整个事务的尾部。 其他的sessions 不能插入 当 AUTO-INC 表被锁定

InnoDB 获取先前初始化的自增列的值 不需要设置任何锁

如果一个外键的约束是在表上定义,

LOCK TABLES 设置表锁, 但是它是更高的MySQL 层次 在InnoDB 层面之上

InnoDB 担心表锁 如果 innodb_table_locks = 1 (the default) 和 autocommit = 0,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

scan724

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值