前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入浅出表锁(Table Lock)

深入浅出表锁(Table Lock)

作者头像
一个风轻云淡
发布2022-11-15 15:36:49
9520
发布2022-11-15 15:36:49
举报
文章被收录于专栏:java学习java

        读锁 :也称为 共享锁 、英文用 S 表示。针对同一份数据,多个事务的读操作可以同时进行而不会 互相影响,相互不阻塞的。         写锁 :也称为 排他锁 、英文用 X 表示。当前写操作没有完成前,它会阻断其他写锁和读锁。这样 就能确保在给定的时间里,只有一个事务能执行写入,并防止其他用户读取正在写入的同一资源。  需要注意的是对于 InnoDB 引擎来说,读锁和写锁可以加在表上,也可以加在行上。

 表级别的S锁、X锁

在对某个表执行SELECT、INSERT、DELETE、UPDATE语句时,InnoDB存储引擎是不会为这个表添加表级 别的 S锁 或者 X锁 的。在对某个表执行一些诸如 ALTER TABLE 、 DROP TABLE 这类的 DDL 语句时,其 他事务对这个表并发执行诸如SELECT、INSERT、DELETE、UPDATE的语句会发生阻塞。同理,某个事务 中对某个表执行SELECT、INSERT、DELETE、UPDATE语句时,在其他会话中对这个表执行 DDL 语句也会 发生阻塞。这个过程其实是通过在 server层 使用一种称之为 元数据锁 (英文名: Metadata Locks , 简称 MDL )结构来实现的。

一般情况下,不会使用InnoDB存储引擎提供的表级别的 S锁 和 X锁 。只会在一些特殊情况下,比方说 崩 溃恢复 过程中用到。比如,在系统变量 autocommit=0,innodb_table_locks = 1 时, 手动

获取InnoDB存储引擎提供的表t 的 S锁 或者 X锁 可以这么写:

代码语言:javascript
复制
LOCK TABLES t READ 
InnoDB存储引擎会对表 t 加表级别的 S锁 。

LOCK TABLES t WRITE 
InnoDB存储引擎会对表 t 加表级别的 X锁 。

不过尽量避免在使用InnoDB存储引擎的表上使用 LOCK TABLES 这样的手动锁表语句,它们并不会提供 什么额外的保护,只是会降低并发能力而已。InnoDB的厉害之处还是实现了更细粒度的 行锁  

MySQL的表级锁有两种模式

表共享读锁(Table Read Lock)

表独占写锁(Table Write Lock)

意向锁 (intention lock) 

InnoDB 支持多粒度锁(multiple granularity locking) ,它允许行级锁与表级锁共存,而意向 锁就是其中的一种表锁 。

意向锁分为两种

意向共享锁(intention shared lock, IS)

事务有意向对表中的某些行加共享锁(S锁)

-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。 SELECT column FROM table ... LOCK IN SHARE MODE;

意向排他锁(intention exclusive lock, IX)

事务有意向对表中的某些行加排他锁(X锁)  

-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。 SELECT column FROM table ... FOR UPDATE;

即:意向锁是由存储引擎 自己维护的 ,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前,InooDB 会先获取该数据行 所在数据表的对应意向锁 。

意向锁的并发性

意向锁不会与行级的共享 / 排他锁互斥!正因为如此,意向锁并不会影响到多个事务对不同数据行加排 他锁时的并发性。(不然我们直接用普通的表锁就行了)

(一条数据从被锁定到被释放的过程中,可 能存在多种不同锁,但是这里我们只着重表现意向锁)

1. InnoDB 支持 多粒度锁 ,特定场景下,行级锁可以与表级锁共存。 2. 意向锁之间互不排斥,但除了 IS与S兼容外, 意向锁会与 共享锁 / 排他锁 互斥 。 3. IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突。 4. 意向锁在保证并发性的前提下,实现了 行锁和表锁共存且满足事务隔离性 的要求

 自增锁(AUTO-INC锁)

在使用MySQL过程中,我们可以为表的某个列添加 AUTO_INCREMENT 属性。举例:

代码语言:javascript
复制
CREATE TABLE `teacher` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

由于这个表的id字段声明了AUTO_INCREMENT,意味着在书写插入语句时不需要为其赋值,SQL语句修改 如下所示。  

代码语言:javascript
复制
INSERT INTO `teacher` (name) VALUES ('zhangsan'), ('lisi');

上边的插入语句并没有为id列显式赋值,所以系统会自动为它赋上递增的值,结果如下所示。

现在我们看到的上面插入数据只是一种简单的插入模式,所有插入数据的方式总共分为三类,分别是 “ Simple inserts ”,“ Bulk inserts ”和“ Mixed-mode inserts ”。

“Simple inserts” (简单插入)  

可以 预先确定要插入的行数 (当语句被初始处理时)的语句。包括没有嵌套子查询的单行和多行INSERT...VALUES() 和 REPLACE 语句。比如我们上面举的例子就属于该类插入,已经确定要插入的行 数。

“Bulk inserts” (批量插入)

事先不知道要插入的行数 (和所需自动递增值的数量)的语句。比如 INSERT ... SELECT , REPLACE ... SELECT 和 LOAD DATA 语句,但不包括纯INSERT。 InnoDB在每处理一行,为AUTO_INCREMENT列 分配一个新值。

“Mixed-mode inserts” (混合模式插入)  

这些是“Simple inserts”语句但是指定部分新行的自动递增值。例如 INSERT INTO teacher (id,name) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d'); 只是指定了部分id的值。另一种类型的“混 合模式插入”是 INSERT ... ON DUPLICATE KEY UPDATE 。

 innodb_autoinc_lock_mode有三种取值,分别对应与不同锁定模式:

(1)innodb_autoinc_lock_mode = 0(“传统”锁定模式)

在此锁定模式下,所有类型的insert语句都会获得一个特殊的表级AUTO-INC锁,用于插入具有AUTO_INCREMENT列的表。这种模式其实就如我们上面的例子,即每当执行insert的时候,都会得到一个 表级锁(AUTO-INC锁),使得语句中生成的auto_increment为顺序,且在binlog中重放的时候,可以保证master与slave中数据的auto_increment是相同的。因为是表级锁,当在同一时间多个事务中执行insert的 时候,对于AUTO-INC锁的争夺会 限制并发 能力。

(2)innodb_autoinc_lock_mode = 1(“连续”锁定模式)

在 MySQL 8.0 之前,连续锁定模式是 默认 的。

在这个模式下,“bulk inserts”仍然使用AUTO-INC表级锁,并保持到语句结束。这适用于所有INSERT ... SELECT,REPLACE ... SELECT和LOAD DATA语句。同一时刻只有一个语句可以持有AUTO-INC锁。

对于“Simple inserts”(要插入的行数事先已知),则通过在 mutex(轻量锁) 的控制下获得所需数量的 自动递增值来避免表级AUTO-INC锁, 它只在分配过程的持续时间内保持,而不是直到语句完成。不使用 表级AUTO-INC锁,除非AUTO-INC锁由另一个事务保持。如果另一个事务保持AUTO-INC锁,则“Simple inserts”等待AUTO-INC锁,如同它是一个“bulk inserts”。

(3)innodb_autoinc_lock_mode = 2(“交错”锁定模式)

从 MySQL 8.0 开始,交错锁模式是 默认 设置。 在此锁定模式下,自动递增值 保证 在所有并发执行的所有类型的insert语句中是 唯一 且 单调递增 的。但 是,由于多个语句可以同时生成数字(即,跨语句交叉编号),为任何给定语句插入的行生成的值可能 不是连续的。

元数据锁(MDL锁)

MySQL5.5引入了meta data lock,简称MDL锁,属于表锁范畴。MDL 的作用是,保证读写的正确性。比 如,如果一个查询正在遍历一个表中的数据,而执行期间另一个线程对这个 表结构做变更 ,增加了一 列,那么查询线程拿到的结果跟表结构对不上,肯定是不行的。

因此,当对一个表做增删改查操作的时候,加 MDL读锁;当要对表做结构变更操作的时候,加 MDL 写 锁

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  •  表级别的S锁、X锁
    • MySQL的表级锁有两种模式
    • 意向锁 (intention lock) 
      • 意向锁分为两种
        • 意向共享锁(intention shared lock, IS)
        • 意向排他锁(intention exclusive lock, IX)
      • 意向锁的并发性
      •  自增锁(AUTO-INC锁)
        • “Simple inserts” (简单插入)  
          • “Bulk inserts” (批量插入)
            • “Mixed-mode inserts” (混合模式插入)  
              • (1)innodb_autoinc_lock_mode = 0(“传统”锁定模式)
              • (2)innodb_autoinc_lock_mode = 1(“连续”锁定模式)
              • (3)innodb_autoinc_lock_mode = 2(“交错”锁定模式)
          • 元数据锁(MDL锁)
          相关产品与服务
          云数据库 SQL Server
          腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档