一.锁

我们通常概念里的锁,是用来处理线程安全问题,锁(latch)的对象是线程,而在mysql中通常所说的锁(lock),是用来实现事务的acid特性的一种手段,也就是锁(lock)的对象是事务,而mysql锁(lock)是由多线程锁(latch)来实现.

二.锁的粒度

锁分为两种,一个读锁(共享锁),一种写锁(互斥锁),只有读锁与读锁之间兼容,写锁和读锁,以及写锁与写锁之间都是不兼容的,a获取了某条记录的读锁,b如果想要修改这条记录,那只有当a事务回滚或者提交释放该记录上的锁,b事务才能进行操作,否则一直阻塞下去(当然mysql有锁的超时时间可以设置),而在mysql中,当a事务想要在记录上加一个写锁时,它需要在表上面加上一个意向写锁,想要加一个读锁时,需要在表上加一个意向读锁,意向锁之间都是兼容的,兼容性见下表:

锁兼容

写锁

意向写锁

读锁

意向读锁

写锁

x

x

x

x

意向写锁

x

x

读锁

x

x

意向读锁

x

从上面表格可以看出,意向锁之间都是互相兼容的,不存在互斥的情况,而真正兼不兼容的是由下一层级的锁来控制,当a事务在某一条记录上加上写锁时,代表着这张表也加上了意向写锁,此时若想在表上加写锁时就会阻塞,比如,a事务没有提交,想要修改表字段或者删除表:

我在a事务中的查询添加了写锁,此时test表上是有意向写锁的,如果我再去删除这张表,此时就会阻塞:

写锁.png

删表.png

同时,意向锁也代表了,下一层级,事务想要加锁的类型,另外mysql中的意向锁都是表锁

我们用show engine innodb status 可以看到我们想要看到意向锁的信息:

image.png

首先是第一行1292代表了这个事务的id,事务id本地是唯一的,且自增的一个数字,(很多功能都有用到事务id,如基于gtid的复制,mvcc中通过undolog读取事务之前的数据达到非锁定一致性读的效果,再比如线上出现阻塞可以通过事务id,查找到线程id,从而可以进行杀死),看第四行,已经说的很明确了,1292这个事务,在表test上加了一个IX锁即意向写锁,I为intention(意向的意思),如果有小伙伴打印出来的效果很简明,没有说到具体锁的情况,建议打开innodb_status_output_locks这个参数,(也建议小伙伴们用5.7这个版本)可以查看到锁的更多信息,除此之外我们还可以通过information_schema.innodb_trx这张表,看到一些信息:

trx.png

trx_tables_locked代表着当前锁定表的个数,也就是加意向锁表的个数,而trx_lock_structs代表锁的种类,也就是表锁和行锁.

三.锁的算法:

首先需要说明的是,数据库上的锁都是作用在索引上面的,我们看一个例子,a表中是有主键索引,而b中没有索引,通过某一列来更新数据,查看整个锁的情况:

image.png

a和b中的数据是一样的,唯一的不一样就是a表中id是主键,而b表中没有索引

先对a表进行查询加写锁:

image.png,

看下加锁情况:

image.png

我们看下标红的地方,1 row locks代表着,我们这次加锁只加了一行的锁,而第二个红框 lock_mode x locks rec

but not gap record lock,代表着它锁定的是一条记录,而不是一个范围,我们先了解下这个,待会后面会说到这个问题.第三个红框0:代表着加锁的数据是2,下面的1和2和mysql具体加锁的实现有关系,我们可以不用关心

我们在看下b表是什么情况:

image.png

我们看下红色的那部分,这边总共显示了6条数据,第一条我们可以不用管他,对于b表,它总共锁住了5条记录,而b表总共就5条记录(因为b表没有主键,0这一行代表是mysql给b表默认添加的6个字节的主键,真正的数据是3这个位置,5列刚好对应的数据是1,2,3,4,5);

好了,介绍完锁具体是作用在索引上,那我们就对锁的实现来进一步探讨.

1.Record lock

Record lock应该是最好理解和解释的一把锁,它所作用的对象就是一行记录,比如,我需要通过唯一索引或者主键来操作数据,这时只会锁住这一行记录,就是在上面,我们通过id为2来操作a表,通常能够出现record lock的情况就是,这条数据能够在表中确定唯一性,如果是通过非唯一索引去操作,mysql需要确定非唯一索引的位置,所以会锁住一定的范围,而使用gap锁

2.gap lock

首先要说的是,gap锁是一个范围,比如,a表中b列有1,3,5,7,9这几条数据(b是非唯一索引),想通过5这条数据来操作,这时会锁住(3,5],(5,7)这样一个范围,其中加在7上面的锁就是gap锁,不包含7,别的事务对3,和7都可以操作,如果想要在3-5之间插入4,或者5-6之间插入6,那就会阻塞

image.png

在另外一个事务中进行修改操作

image.png

image.png

从这张图我们可以看出,3,7的这两数其实是没有锁住的,是可以修改的,但是想往3-5或者5-7之间插入数据也是不行的,此处需要注意下,我在修改时,都是把修改后的值尽量远离这个范围,如update z set b = 9 where b = 7,如果是执行update z set b = 5 where b = 7,这样一句话是同样会阻塞的,虽然7这条记录没有锁住,但是把原有的数修改为锁住的这条记录,会修改索引的结构,也会导致阻塞;

3.next key lock

next key lock 是gap lock+record lock的结合,也是一个范围的概念,比如说有a表中有1,3,5,7,9这样几条数据,比如执行delete from a where b <=7,此时锁住的范围就是(-∞,1],(1,3],(3,5],(5,7]此时加在7上的锁就是next key lock,和gap lock的区别就是有没有包含7这样一条记录,如果我在另外一个事务中对7进行修改会造成阻塞.

image.png

image.png

四.最后

实际上mysql的锁机制是非常复杂的,这里只能说是简单介绍下mysql的锁,其中在粒度上,可以分为表锁和行锁,表锁是意向锁,意向锁之间互相兼容,而算法上只介绍了record lock,gap lock和next key lock,除此之外还有insert intention lock,auto-inc locks,通常mysql是会用next key lock,如果遇到能够确定的一行,比如主键,会将next key lock优化为record,具体会使用到哪种锁,又需要根据具体的sql语句来查看,另外,mysql的锁机制也是保证acid的特性,比如,next-key lock的出现其实就是为了解决幻读问题,在不同的隔离级别下,展现出的效果是不一样的,有兴趣的同学可以仔细研究研究,最后,文章若有不妥的地方,欢迎大家指出批评,共同进步,感谢大家.

[参考自:innodb技术内幕]

mysql锁在粒度上分为_mysql锁的简单理解相关推荐

  1. mysql 显示帐号被锁定_mysql锁

    1. 查看表锁命令 mysql> show open tables; In_use为0 ,表示没有锁表 2. 锁表 2.1 给表上读锁 lock table tb_emp read; 2.2 给 ...

  2. mysql行锁同索引键问题_mysql 锁问题 (相同索引键值或同一行或间隙锁的冲突)

    1.使用相同索引键值的冲突 由于mysql 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但如果是使用相同的索引键,是会出现锁冲突的.设计时要注意 例如:city表city_ ...

  3. centos写mysql光标移到上一行_mysql:一条SQL更新语句(update)是如何执行的

    一条更新语句的执行流程又是怎样的呢? 之前你可能经常听DBA同事说,MySQL可以恢复到半个月内任意一秒的状态,惊叹的同时,你是不是心中也会不免会好奇,这是怎样做到的呢? 我们还是从一个表的一条更新语 ...

  4. mysql基础命令返回上一级_MySQL基础 — 常用命令

    一.连接MySQL 格式:mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MySQ: 首先在打开cmd窗口,输入mysql -uroot -p ,然后空格进入MySQL控制台,M ...

  5. mysql数据库在什么上运行_mysql – 在所有数据库上运行SQL查询

    我有一个使用cPanel和phpmyadmin的托管帐户. 我在此帐户下有50个数据库,所有WordPress. 我需要修改此查询,以便它运行所有数据库以更新密码. UPDATE 'wp_users' ...

  6. mysql使用索引下推的好处_mysql的索引下推理解和实践

    对于mysql建表稍有点经验的开发人员都会为后续的where查询条件提前考虑创建索引. 这里说的是在使用索引查询时有关索引下推的有关知识点. 综合前人的经验结果:索引下推是数据库检索数据过程中为减少回 ...

  7. mysql 事物隔离界别_MySQL锁与事务隔离级别

    ------------恢复内容开始------------ 一.概述 1.锁的定义 锁是计算机协调多个进程或线程并发访问某一资源的机制. 在数据库中,除了传统的计算资源(如CPU.RAM.IO等)的 ...

  8. mysql 锁的类型_mysql锁的分类

    一. 按照对数据操作的粒度分为:表级锁.行级锁.页级锁.间隙锁 MyISAM和MEMORY采用表级锁(table-level locking) BDB采用页面锁(page-level locking) ...

  9. mysql 表级别的锁和行级别的_MySQL 表锁和行锁机制

    案例分析 目前,MySQL常用的存储引擎是InnoDB,相对于MyISAM而言.InnoDB更适合高并发场景,同时也支持事务处理.我们通过下面这个案例(坑),来了解行锁和表锁. 业务:因为订单重复导入 ...

最新文章

  1. 7号团队:团队任务3-每日任务(2018-11-26)
  2. 【ArcGIS for Android】基于位置查询Graphic和Feature
  3. 【转】tomcat性能调优
  4. spring:如何用代码动态向容器中添加或移除Bean ?
  5. linux写程序四则运算,Shell编程之变量及四则运算
  6. 如何实现一个符合泊松分布的即时消息发生器?
  7. python常用魔术方法
  8. 基于进程的游戏Server端架构设计
  9. FirstApp,iphone开发学习总结1,UIview添加UIimage
  10. 为何大厂APP如微信、支付宝、淘宝、手Q等只适配了armeabi-v7a/armeabi?
  11. java集合面试题总结
  12. 创客教室-中小学创客教育课程介绍
  13. 个税计算公式excel_财务不会做工资表?全函数统计查询、自动个税计算模板送你,给力...
  14. 代价敏感随机森林Python附代码
  15. Linux CentOS 服务器清理磁盘空间
  16. 机械工程学专业词汇英语翻译
  17. excel两个指标相关性分析_用Excel做相关性分析
  18. 求余数(c++基础)
  19. linux 进程 ksoftirqd/n 占用cpu 100%
  20. 分支过程灭绝概率matlab,一类年龄结构相关的两性分支过程的灭绝概率

热门文章

  1. grub开机选项中没有linux,安装 Ubuntu 后 Grub 开机选项中的 Fedora 不见了
  2. pytorch实现基本AutoEncoder与案例
  3. Docker下载与安装(win7,8,10,mac)
  4. Bash脚本删除相对路径下小于指定大小的文件
  5. mysql上一条语句成功_mysql : 获取上一条insert语句
  6. tplink迷你路由器中继模式_斐讯无线路由器设置无线中继(无线扩展)
  7. php 跳转到另外一个php,PHP: 其他变更 - Manual
  8. 高性能MYSQL读书笔记1
  9. poj 1185 火炮 (减少国家DP)
  10. Nagios3完整配置文档