mysql中innodb引擎的行锁是通过加在啥上完成

author author     2023-04-11     532

关键词:

参考技术A

行锁的等待

在介绍如何解决行锁等待问题前,先简单介绍下这类问题产生的原因。产生原因简述:当多个事务同时去操作(增删改)某一行数据的时候,MySQL 为了维护 ACID 特性,就会用锁的形式来防止多个事务同时操作某一行数据,避免数据不一致。只有分配到行锁的事务才有权力操作该数据行,直到该事务结束,才释放行锁,而其他没有分配到行锁的事务就会产生行锁等待。如果等待时间超过了配置值(也就是 innodb_lock_wait_timeout 参数的值,个人习惯配置成 5s,MySQL 官方默认为 50s),则会抛出行锁等待超时错误。


如上图所示,事务 A 与事务 B 同时会去 Insert 一条主键值为 1 的数据,由于事务 A 首先获取了主键值为 1 的行锁,导致事务 B 因无法获取行锁而产生等待,等到事务 A 提交后,事务 B 才获取该行锁,完成提交。这里强调的是行锁的概念,虽然事务 B 重复插入了主键,但是在获取行锁之前,事务一直是处于行锁等待的状态,只有获取行锁后,才会报主键冲突的错误。当然这种 Insert 行锁冲突的问题比较少见,只有在大量并发插入场景下才会出现,项目上真正常见的是 update&delete 之间行锁等待,这里只是用于示例,原理都是相同的。


根据我之前接触到的此类问题,大致可以分为以下几种原因:

1. 程序中非数据库交互操作导致事务挂起将接口调用或者文件操作等这一类非数据库交互操作嵌入在 SQL 事务代码之中,那么整个事务很有可能因此挂起(接口不通等待超时或是上传下载大附件)。


2. 事务中包含性能较差的查询 SQL事务中存在慢查询,导致同一个事务中的其他 DML 无法及时释放占用的行锁,引起行锁等待。

3. 单个事务中包含大量 SQL通常是由于在事务代码中加入 for 循环导致,虽然单个 SQL 运行很快,但是 SQL 数量一大,事务就会很慢。

4. 级联更新 SQL 执行时间较久这类 SQL 容易让人产生错觉,例如:update A set ... where ...in (select B) 这类级联更新,不仅会占用 A 表上的行锁,也会占用 B 表上的行锁,当 SQL 执行较久时,很容易引起 B 表上的行锁等待。

5. 磁盘问题导致的事务挂起极少出现的情形,比如存储突然离线,SQL 执行会卡在内核调用磁盘的步骤上,一直等待,事务无法提交。综上可以看出,如果事务长时间未提交,且事务中包含了 DML 操作,那么就有可能产生行锁等待,引起报错。

参考技术B 概念:
锁是用来管理对共享文件的并发访问。innodb会在行级别上对数据库上锁。不过innodb存储引擎会在数据库内部其他多个地方使用锁,从而允许对不同资源提供并发访问。例如操作缓冲池中的LRU列表,删除,添加,移动LRU列表中的元素,为了保证一致性,必须有锁的介入。MyISAM引擎是表锁,而InnoDB提供一致性的非锁定读、行级锁,且行级锁没有相关额外的开销。

table-level locking(表级锁)
整个表被客户锁定。根据锁定的类型,其他客户不能向表中插入记录,甚至从中读数据也受到限制MyISAM、MEMORY默认锁级别,个别时候,InnoDB也会升级为表级锁
row-level locking(行级锁)
只有线程当前使用的行被锁定,其他行对于其他线程都是可用的InnoDB默认行级锁。是基于索引数据结构来实现的,而不是像ORACLE的锁,是基于block的。InnoDB也会升级为表级锁,全表/全索引更新,请求autoinc锁等
page-level locking(页级锁)
锁定表中某些行集合(称做页),被锁定的行只对锁定最初的线程是可行。如果另外一个线程想要向这些行写数据,它必须等到锁被释放。不过其他页的行仍然可以使用BDB默认页级锁
lock与latch
latch称为闩锁(轻量级的锁),因为其要求锁定的时间必须非常短。若持续的时间长,则应用的性能会非常差。在InnoDB存储引擎中,又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制。latch可以通过命令show engine innodb mutex来进行查看。如图:

由上图可以看出列Type显示的总是InnoDB,列Name显示latch的信息以及所在源码的行数,列Status中显示的os_waits表示操作系统等待的次数。
lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或者rollback后释放(不同事务隔离级别释放的时间可能不一样)。有死锁机制。二则的区别如下:

特点:
InnoDB是通过对索引上的索引项加锁来实现行锁。这种特点也就意味着,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。
锁的类型:
有两种标准的行级锁:
共享锁(S lock):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁.SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排它锁(X lock):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他锁.SELECT * FROM table_name WHERE ... FOR UPDATE
InnoDB存储引擎支持意向锁且设计比较简练,分为两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。(意向锁是InnoDB自动加的)
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁.
意向独占锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁.本回答被提问者采纳

mysql-锁

InnoDB行锁实现方式InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,... 查看详情

mysql行锁

...持行锁。不支持行锁意味着并发控制只能使用表锁,InnoDB是支持行锁的,这也是MyISAM 查看详情

mysql行锁

...持行锁。不支持行锁意味着并发控制只能使用表锁,InnoDB是支持行锁的,这也是MyISAM 查看详情

行锁功过:怎么减少行锁对性能的影响?

...时刻只能有一个更新在执行,这就会影响到业务并发度。InnoDB是支持行锁的,这也是MyISAM被InnoDB替代的重要原因之一。我们今天就主要来聊聊InnoDB的行锁,以及如何通过减少锁冲突来提升业务并发度。顾名思义, 查看详情

从头开始搞懂mysql(05)行锁表锁全局锁(代码片段)

...是所有的引擎都支持行锁,比如MyISAM就不支持,InnoDB支持行锁,避免了并发控制时使用表锁1.1两阶段锁在InnoDB事务中,行锁是在需要的时候才被加上的,但并不是不需要了就立刻释放,而是等待事务结束后... 查看详情

面试题2:mysql的行锁

mysql的锁是由具体的存储引擎实现的。InnoDB支持行锁和事务Mysql有三种级别的锁定:表级锁定、页级锁定、行级锁定  查看详情

mysql中innodb的行锁算法

参考技术A众所周知,innodb是默认行锁,当然也支持表锁。如下是对于行锁的算法进行的一些实验。锁的算法为:我知道是行锁,但是是如何锁的,锁多少数据假如有个索引是:[1,2,3,7]recordlock锁的是1,2,3,7gaplock锁的是(-,... 查看详情

day871.行锁-mysql实战(代码片段)

...只能有一个更新在执行,这就会影响到业务并发度。InnoDB是支持行锁的 查看详情

mysql原理篇之锁--14(代码片段)

...写操作多粒度锁MySQL中的行锁和表锁其他存储引擎中的锁InnoDB存储引擎中的锁InnoDB中的表级锁InnoDB中的行级锁InnoDB锁的内存结构解决并发事务带来问题的两种基本 查看详情

表锁行锁页锁是什么区别

表级锁(table-levellocking):MyISAM和MEMORY存储引擎行级锁(row-levellocking):InnoDB存储引擎页面锁(page-level-locking):BDB存储引擎表级锁:开销小,并发低, 查看详情

mysql锁机制(代码片段)

....1.1MySQL表锁2.1.2MyISAM加锁方式2.1.3写阻塞读2.1.4读阻塞写2.2InnoDB锁的实现2.2.1InnoDB行锁2.2.2行锁加锁方式2.2.3行锁实现方式2.2.4意向锁2.2.5间隙锁(GapLocks)2.2.6临键锁(Next-KeyLocks)2.2.7自增锁(AUTO-INCLocks)3死锁3.1MyISAM死锁3.2InnoDB死锁4锁监控4... 查看详情

大牛总结的mysql锁优化

...了主要就是查询数据,对数据的插入,更新操作比较少。InnoDB存储引擎,它支持事务,其设计目标主要面向在线事务处理(OLTP)的应用。其特点是行锁设计、支持外键,并支持类似于Oracle的非锁定读,即默认读取操作不会产生锁。... 查看详情

mysql的行锁

...ff09;和排他锁(X锁)。一般普通的select语句,InnoDB不加任何锁,我们称之为快照读select*fromtest;通过加S锁和X锁的select语句或者插入/更新/删除操作,我们称之为当前读select*fromtestlockinsharemode;select*fromtestforupdate;i... 查看详情

mysql基础篇之行锁--07(代码片段)

...级锁,今天我们就来讲讲MySQL的行锁。MySQL的行锁是在引擎层由各个引擎自己实现的。但并不是所有的引擎都支持行锁,比如MyISAM引擎就不支持行锁。不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,... 查看详情

mysql的行锁与表锁(select*....forupdate)

参考技术A  mysql中使用selectforupdate的必须针对InnoDb,并且是在一个事务中,才能起作用。  select的条件不一样,采用的是行级锁还是表级锁也不一样。  由于InnoDB预设是Row-LevelLock,所以只有「明确」的指定主键,MySQL才会... 查看详情

mysql中的全文本搜索用在啥情况下?

...统来决定了。  而MySQL另外一个最流行的存储引擎之一Innodb存储数据的策略是分为两种的,一种是共享表空间存储方式,还有一种是独享表空间存储方式。  当使用共享表空间存储方式的时候,Innodb的所有数据保存在一个单... 查看详情

mysql锁--02---行锁(记录锁(recordlocks))(代码片段)

...何生成可参考右边的帮助文档文章目录前置知识行锁特点InnoDB与MyISAM的最大不同有两点:==行锁支持事务==ACID并发事务带来的问题事务隔离级别常看当前数据库的事务隔离级别:showvariableslike'tx_isolation';M... 查看详情

mysql索引

...排序存放,提高查询效率;一张表中可以添加多个索引;innodb存储引擎默认使用的是b+tree索引结构,也支持哈希、全文索引。    2.索引的优缺点    2.1索引的优点    ①提高数据库查询效率    ②减少锁等待... 查看详情