首页 > 数据库 >MySQL锁系列(一)之锁的种类和概念

MySQL锁系列(一)之锁的种类和概念

时间:2024-03-04 22:35:19浏览次数:27  
标签:之锁 系列 lock implicit Locks mode MySQL table id

原文链接

https://keithlan.github.io/2017/06/05/innodb_locks_1/

背景


锁是MySQL里面最难理解的知识,但是又无处不在。
一开始接触锁的时候,感觉被各种锁类型和名词弄得晕头转向,就别说其他了。
本文是通过DBA的视角(非InnoDB内核开发)来分析和窥探锁的奥秘,并解决实际工作当中遇到的问题

锁的种类&概念

想要啃掉这块最难的大骨头,必须先画一个框架,先了解其全貌,才能逐个击破

  • Shared and Exclusive Locks
* Shared lock: 共享锁,官方描述:permits the transaction that holds the lock to read a row   eg:select * from xx where a=1 lock in share mode   * Exclusive Locks:排他锁: permits the transaction that holds the lock to update or delete a row   eg: select * from xx where a=1 for update
  • Intention Locks
1. 这个锁是加在table上的,表示要对下一个层级(记录)进行加锁 2. Intention shared (IS):Transaction T intends to set S locks on individual rows in table t 3. Intention exclusive (IX): Transaction T intends to set X locks on those rows 4. 在数据库层看到的结果是这样的: TABLE LOCK table `lc_3`.`a` trx id 133588125 lock mode IX
  • Record Locks
1. 在数据库层看到的结果是这样的: RECORD LOCKS space id 281 page no 3 n bits 72 index PRIMARY of table `lc_3`.`a` trx id 133588125 lock_mode X locks rec but not gap   2. 该锁是加在索引上的(从上面的index PRIMARY of table `lc_3`.`a` 就能看出来)   3. 记录锁可以有两种类型:lock_mode X locks rec but not gap && lock_mode S locks rec but not gap
  • Gap Locks
1. 在数据库层看到的结果是这样的: RECORD LOCKS space id 281 page no 5 n bits 72 index idx_c of table `lc_3`.`a` trx id 133588125 lock_mode X locks gap before rec   2. Gap锁是用来防止insert的   3. Gap锁,中文名间隙锁,锁住的不是记录,而是范围,比如:(negative infinity, 10),(10, 11)区间,这里都是开区间哦
  • Next-Key Locks
1. 在数据库层看到的结果是这样的: RECORD LOCKS space id 281 page no 5 n bits 72 index idx_c of table `lc_3`.`a` trx id 133588125 lock_mode X   2. Next-Key Locks = Gap Locks + Record Locks 的结合, 不仅仅锁住记录,还会锁住间隙,比如: (negative infinity, 10】,(10, 11】区间,这些右边都是闭区间哦
  • Insert Intention Locks
1. 在数据库层看到的结果是这样的: RECORD LOCKS space id 279 page no 3 n bits 72 index PRIMARY of table `lc_3`.`t1` trx id 133587907 lock_mode X insert intention waiting   2. Insert Intention Locks 可以理解为特殊的Gap锁的一种,用以提升并发写入的性能
  • AUTO-INC Locks
1. 在数据库层看到的结果是这样的: TABLE LOCK table xx trx id 7498948 lock mode AUTO-INC waiting   2. 属于表级别的锁   3. 自增锁的详细情况可以之前的一篇文章: http://keithlan.github.io/2017/03/03/auto_increment_lock/
  • 显示锁 vs 隐示锁
* 显示锁(explicit lock) 显示的加锁,在show engine innoDB status 中能够看到 ,会在内存中产生对象,占用内存 eg: select ... for update , select ... lock in share mode   * 隐示锁(implicit lock) implicit lock 是在索引中对记录逻辑的加锁,但是实际上不产生锁对象,不占用内存空间   * 哪些语句会产生implicit lock 呢? eg: insert into xx values(xx) eg: update xx set t=t+1 where id = 1 ; 会对辅助索引加implicit lock   * implicit lock 在什么情况下会转换成 explicit lock eg: 只有implicit lock 产生冲突的时候,会自动转换成explicit lock,这样做的好处就是降低锁的开销 eg: 比如:我插入了一条记录10,本身这个记录加上implicit lock,如果这时候有人再去更新这条10的记录,那么就会自动转换成explicit lock   * 数据库怎么知道implicit lock的存在呢?如何实现锁的转化呢? 1. 对于聚集索引上面的记录,有db_trx_id,如果该事务id在活跃事务列表中,那么说明还没有提交,那么implicit则存在 2. 对于非聚集索引:由于上面没有事务id,那么可以通过上面的主键id,再通过主键id上面的事务id来判断,不过算法要非常复杂,这里不做介绍
  • metadata lock
1. 这是Server 层实现的锁,跟引擎层无关 2. 当你执行select的时候,如果这时候有ddl语句,那么ddl会被阻塞,因为select语句拥有metadata lock,防止元数据被改掉
  • 锁迁移
1. 锁迁移,又名锁继承 2. 什么是锁迁移呢? a) 满足的场景条件: b)我锁住的记录是一条已经被标记为删除的记录,但是还没有被puge c) 然后这条被标记为删除的记录,被purge掉了 d) 那么上面的锁自然而然就继承给了下一条记录,我们称之为锁迁移
  • 锁升级
锁升级指的是:一条全表更新的语句,那么数据库就会对所有记录进行加锁,那么可能造成锁开销非常大,可能升级为页锁,或者表锁。 MySQL 没有锁升级
  • 锁分裂
1. InnoDB的实现加锁,其实是在页上面做的,没有办法直接对记录加锁 2. 一个页被读取到内存,然后会产生锁对象,锁对象里面会有位图信息来表示哪些heapno被锁住,heapno表示的就是堆的序列号,可以认为就是定位到某一条记录 3. 大家又知道,由于B+tree的存在,当insert的时候,会产生页的分裂动作 4. 如果页分裂了,那么原来对页上面的加锁位图信息也就变了,为了保持这种变化和锁信息,锁对象也会分裂,由于继续维护分裂后页的锁信息
  • 锁合并
锁的合并,和锁的分裂,其实原理是一样的,参考上面即可。   至于锁合并和锁分裂的算法,比较复杂,这里就不介绍了
  • latch vs lock
* latch mutex rw-lock 临界资源用完释放 不支持死锁检测 以上是应用程序中的锁,不是数据库的锁   * lock 当事务结束后,释放 支持死锁检测 数据库中的锁

锁的兼容矩阵

  • X vs S
兼容性XS
X N N
S N Y
  • IS,IX,S,X
兼容性ISIXSX
IS Y Y Y N
IX Y Y N N
S Y N Y N
X N N N N
  • AI,IS,IX,S,X
兼容性AIISIXSX
AI N Y Y N N
IS Y Y Y Y N
IX Y Y Y N N
S N Y N Y N
X N N N N N

参考资料

1 2 3 1. https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html 2. MySQL技术内幕:InnoDB 存储引擎 3. MySQL内核:InnoDB 存储引擎  

标签:之锁,系列,lock,implicit,Locks,mode,MySQL,table,id
From: https://www.cnblogs.com/lingyejun/p/18052879

相关文章

  • 推荐一个Mysql客户端命令行神器
    目录软件主页安装选项参考命令链接数据库参考网址​​ 今个推荐一个MySQL命令行客户端---MyCli,其支持命令的自动补全和语法高亮;软件主页MyCli--HomePags安装#Mycli支持在Python环境,MacOS,Windows系统下安装使用,pip3installmycli#Python下安装,解释器......
  • MySQL之事务
    事务什么是事务事务transaction(简写tx),在数据库中,事务是指一组逻辑操作,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与结束之间执行的全部数据库操作组成。事务的作用保证了对数据操作的安全性,保证数据的一致性例子:还钱的例子还钱的账户数......
  • MySQL之索引
    索引知识回顾:数据都是存在于硬盘上的,查询数据不可避免的需要进行IO操作索引:就是一种数据结构,类似于书的目录。意味着以后在查询数据的时候应该先找目录再找数据,而不是一页一页的番薯,从而提升查询熟读降低IO操作。索引在MySQL中也叫“键”,是存储引擎用于快速查找记录的一种数据......
  • MySQL-18 MySQL8其他新特性
    C-18.MySQL8其他新特性1.MySQL8新特性概述MySQL从5.7版本直接跳跃发布了8.0版本,可见是一个令人兴奋的里程碑的版本。MySQL8版本在功能上,做了显著的改进与增强,开发者对MySQL的源代码进行了重构,最突出的一点是对MySQLOptimizer优化器进行了改进。不仅在速度上得到了改善,还为用......
  • C++ mySQL数据库连接池(windows平台)
    C++MySQL数据库连接池新手学了C++多线程,看了些资料练手写了C++数据库连接池小项目,自己的源码地址关键技术点MySQL数据库编程、单例模式、queue队列容器、C++11多线程编程、线程互斥、线程同步通信和unique_lock、基于CAS的原子整形、智能指针shared_ptr、lambda表达式、生产......
  • 【Redis】Redis如何保证和MySQL数据库的数据一致性
    保障MySQL和Redis数据一致性需要使用不同的策略和技术,因为两者是不同的数据存储系统。以下是一些常见的方法:1.数据同步MySQL数据同步至Redis使用事件驱动机制:当MySQL中的数据更新时,通过触发器或者其他事件驱动的机制,将数据同步至Redis。定时任务:定期轮询MySQL数据......
  • C++系列:const关键字
    前言在学习C++时,const关键字的知识点分散在书的各个章节。当我们尝试在编程时使用const时,总会感觉有一些细节被遗忘,因而不能得心应手地使用const关键字。因此,本篇文章尝试着对const关键字的做一些总结。参考书籍《C++PrimerPlus》const总结这里是我做的关于const关键字的一些......
  • mysql语句的执行顺序
    一、sql执行的流程1mysql客户端发送查询请求到服务器。2mysql服务器接收请求并处理,mysql解析器解析查询语句,进行语法分析,确保查询语句符合mysql的语法要求。3mysql的查询优化器对sql语句进行优化处理(选择最合适的索引,或使用其它技术来提高性能),生成执行计划。4mysql执行引......
  • docker系列教程04---容器网络
    一、Docker不启动时默认的网络情况这里先把Docker停掉了,然后咱们ifconfig看一眼:ifconfig ens33不用多说了,lo为回环。这里可能还会有一个virbr0,在CentOS7的安装过程中如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的virbr0网卡(virbr......
  • Ubuntu安装zabbix,初始化数据库报没有这个文件 /usr/share/doc/zabbix-sql-scripts/mys
    报错信息如下: 解决方法:1、先查看是否安装了zabbix-server-mysql,我这里是已经安装过了,但是初始化还是报错找不到文件 2、去zabbix下载对应版本的源码,然后进行手动安装下载链接:https://www.zabbix.com/download_sources#60LTS 3、源码下载后解压,在database文件中找到m......