InnoDB中的锁-意向锁

内容纲要

1.概述

InnoDB支持多粒度锁定,允许行锁和表锁共存。意向锁是在表级别上设置的锁,预示着事务稍后可能会在表中的某行上设置哪种类型的锁(共享锁 or 排他锁)。

意向锁有两种主要类型:

  • 意向共享锁(Intention Shared Lock,简称 IS):表明一个事务打算对表中的某一行设置共享锁。
  • 意向排它锁(Intention Exclusive Lock,简称 IX) :表明一个事务打算对表中的某一行设置排他锁。

例如,对表中的一个数据行执行 SELECT ... FOR SHARE 语句,会设置一个 IS 锁。执行 SELECT ... FOR UPDATE 会设置一个 IX 锁。下面是锁兼容性的矩阵:

X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible

意向锁并不会阻止任何全表请求(例如,LOCK TABLES … WRITE)。意向锁的主要目的是显示有人正在锁定一行,或者准备锁定一行。在"SHOW ENGINE INNODB STATUS"的输出中,意向锁的事务数据可能看起来像这样:

TABLE LOCK table `test`.`t` trx id 10080 lock mode IX

实际上,如果不使用意向锁,要确定表级锁和行级锁之间的冲突,可能需要遍历所有行的行锁。有了意向锁,我们只需要检查是否存在意向锁,就可以确定是否存在行锁。

2.实验部分

首先,我们创建测试表 sys_user

CREATE TABLE `sys_user` (
  `id` int NOT NULL,
  `name_pinyin` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

2.1 冲突实验

然后,我们进行以下操作来测试锁的冲突:

第一步,事务A获取IS锁,代码如下:

# Transaction A 
BEGIN;
SELECT * FROM sys_user WHERE id = 17 lock in share mode;

第二步,事务B尝试获取IX锁,代码如下:

# Transaction B
BEGIN;
SELECT * FROM sys_user WHERE id = 17 FOR UPDATE;

执行以上两步,你会发现事务B阻塞,这是因为IX锁与IS锁冲突。

2.2 兼容测试

接下来,我们测试一些兼容的锁类型。

第一步,事务A获取IS锁,代码如下:

# Transaction A 
BEGIN;
SELECT * FROM sys_user WHERE id = 17 lock in share mode;

第二步,事务B尝试获取S锁,代码如下:

# Transaction B
BEGIN;
SELECT * FROM sys_user WHERE id = 17 lock in share mode;

执行以上两步,你会发现事务B没有阻塞,这是因为S锁与IS锁兼容。这个实验让你明白了InnoDB的意向锁能预防死锁发生,确保数据库操作的顺利进行。

2.3 锁结果查询截图

file

3. 总结

本文深入探讨了InnoDB数据库的意向锁概念,包含意向共享锁和意向排他锁两种,它们在表级别上显示了事务是否正在锁定一行或即将锁定一行。在我们执行 SELECT…FOR SHARE或SELECT…FOR UPDATE语句时,会分别设置 IS和IX锁。

我们也查看了如何在 "SHOW ENGINE INNODB STATUS" 输出中获取意向锁的事务数据。在检查冲突的时候,如果不使用意向锁,我们可能需要遍历所有行的行锁。而有了意向锁,我们只需检查是否存在意向锁,就可以确定是否有行锁。

此外,我们也通过实验的方式,展示了如何在 MySQL 中观察和理解锁的冲突,以及如何测试兼容的锁类型。这对于理解MySQL的锁机制,预防潜在的死锁以及提高数据库操作的顺畅性非常有帮助。

希望能在面试中帮到你。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部