我们的数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能就会导致我们说的脏写、脏读、不可重复读、幻读这些问题。
这些问题的本质都是数据库的多事务并发问题,为了解决多事务并发问题,数据库设计了事务隔离机制、锁机制、MVCC多版本并发控制隔离机制,用一整套机制来解决多事务并发问题。事务隔离机制简单可以理解就是为了满足ACID特性而设计的事务隔离级别,这里不做详细解释。本文主要描述Mysql的锁机制以及MVCC机制。
一、锁
锁的分类有很多种,从加锁思想上分为乐观锁和悲观锁,从加锁粒度上分为表锁和行锁,从对数据的操作类型上分为读锁和写锁(共享锁和排他锁),还有间隙锁和临键锁。下面详细介绍下这些锁。
1、乐观锁和悲观锁
乐观锁是在整个数据处理的过程中,不对数据进行加锁,只在数据处理完成后向数据库提交数据时,才对数据版本进行检查。一般是在表中加一个版本号字段,读取时一并读取数据的版本,提交时对数据的版本做对比,只有此时数据库中的版本与之前读取到的版本一直才进行更新,否则做一些回滚或者重试。
悲观锁是在数据开始处理时就通过数据库本身的读锁或写锁将数据加锁,直到数据处理完成才释放。
2、读写锁(共享锁、排他锁)

如上图可以手动添加读锁,可以看到给当前表加上读锁之后,当前session 对数据的更新操作会报错,而查询操作可以执行。其他session插入或更新则会等待,查询也是可以执行的。


上图中手动添加写锁,当前session对该表的增删改查都没有问题,其他session对该表的所有操作被阻塞。
在Innodb存储引擎中,增删改操作都会自动加写锁,普通的SELECT语句不会加任何锁,如果想加锁,可以使用下面方式:
SELECT * FROM t1 WHERE id = 1 LOCK IN SHARE MODE; – 显式加共享锁
SELECT * FROM t1 WHERE id = 1 FOR UPDATE; – 显式加排他锁
总结:
读锁(共享锁):当事务A给某张表(或行)加上读锁之后,其余事务包括本事务可以读取这个资源,但无法修改。
写锁(排他锁):当事务A对某个资源加上写锁之后,当前事务可以对该资源进行增删改查操作,而其他事务不能对这个资源进行任何操作,直到事务A释放锁。
3、表锁和行锁
表级锁和行级锁只是表示锁的粒度,并不是实际的锁。一般来说,锁粒度越小,锁冲突就越少,系统的并发性能就更高,但同时数据库在管理锁方面的开销也越大,当管理锁的开销比数据存取的开销还要大时,反而可能会影响到系统的性能。
常见的存储引擎中,MyISAM引擎仅支持表级锁,而InnoDB引擎除了支持表级锁外,也支持行级锁(默认)。行级锁可以最大程度地支持并发处理。
注意:无索引行锁会升级为表锁
例如:


第一个Seeion未提交事务,第二个Session会一直阻塞,直到第一个事务提交或第二个事务超时。

InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为
表锁。
4、间隙锁与临键锁
间隙锁,锁的就是两个值之间的空隙。Mysql默认级别是repeatable-read,可能存在幻读的问题,而间隙锁在某些情况下可以解决幻读问题。注意间隙锁只有在可重复读级别下才生效。

如上图中的数据,有间隙(1,4),(4,20),(20,30),(30,正无穷)。

上面第一个Session更新的数据间隙包含(4,30】这个区间,注意最后这个30也是无法操作的,在这个事务没有提交之前,其余的事务无法对这个间隙中的数据进行修改操作(可以查询),会一直阻塞直到前一事务提交为止。如果一直未提交,会超时。
临键锁(Next-key Locks)
Next-Key Locks是行锁与间隙锁的组合。像上面那个例子里的这个(4,30]的整个区间可以叫做临键锁。
锁优化建议
1、尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
2、合理设计索引,尽量缩小锁的范围
3、尽可能减少检索条件范围,避免间隙锁
4、尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行
5、尽可能低级别事务隔离
6、找DBA,让他给出专业的建议,这一方法最有效。
二、MVCC与BufferPool机制
Mysql在可重复读隔离级别下,同样的sql查询语句在一个事务里多次执行查询结果相同,就算其它事务对数据有修改也不会影响当前事务sql语句的查询结果。这个隔离性就是靠MVCC(Multi-Version Concurrency Control)机制来保证的,对一行数据的读和写两个操作默认是不会通过加锁互斥来保证隔离性,避免了频繁加锁互斥。
Mysql在读已提交和可重复读隔离级别下都实现了MVCC机制。
首先要先了解两个概念和一个规则。
undo日志版本链:undo日志版本链是指一行数据被多个事务依次修改过后,在每个事务修改完后,Mysql会保留修改前的数据undo回滚日志,并且用两个隐藏字段trx_id(事务id)和roll_pointer(前一版本数据的指针)把这些undo日志串联起来形成一个历史记录版本链。这个事务id是在每个事务开启之后,递增生成的一个id。
一致性视图read-view:在可重复读隔离级别,当事务开启,执行任何查询sql时会生成当前事务的一致性视图read-view,该视图在事务结束之前都不会变化(如果是读已提交隔离级别在每次执行查询sql时都会重新生成),这个视图由执行查询时所有未提交事务id数组(数组里最小的id为min_id)和已创建的最大事务id(max_id)组成,事务里的任何sql查询结果需要从对应版本链里的最新数据开始逐条跟read-view做比对从而得到最终的快照结果。
数据是否可见规则:

在可重复读隔离级别,当事务开启,执行任何查询sql时会生成当前事务的一致性视图read-view,该视图在事务结束
之前都不会变化(如果是读已提交隔离级别在每次执行查询sql时都会重新生成),这个视图由执行查询时所有未提交事
务id数组(数组里最小的id为min_id)和已创建的最大事务id(max_id)组成,事务里的任何sql查询结果需要从对应
版本链里的最新数据开始逐条跟read-view做比对从而得到最终的快照结果。
版本链比对规则:

  1. 如果 row 的 trx_id 落在绿色部分( trx_id<min_id ),表示这个版本是已提交的事务生成的,这个数据是可见的;
  2. 如果 row 的 trx_id 落在红色部分( trx_id>max_id ),表示这个版本是由将来启动的事务生成的,是不可见的(若
    row 的 trx_id 就是当前自己的事务是可见的);
  3. 如果 row 的 trx_id 落在黄色部分(min_id <=trx_id<= max_id),那就包括两种情况:
    a. 若 row 的 trx_id 在视图数组中,表示这个版本是由还没提交的事务生成的,不可见(若 row 的 trx_id 就是当前自己的事务是可见的);
    b. 若 row 的 trx_id 不在视图数组中,表示这个版本是已经提交了的事务生成的,可见。
    对于删除的情况可以认为是update的特殊情况,会将版本链上最新的数据复制一份,然后将trx_id修改成删除操作的trx_id,同时在该条记录的头信息(record header)里的(deleted_flag)标记位写上true,来表示当前记录已经被
    删除,在查询时按照上面的规则查到对应的记录如果delete_flag标记位为true,意味着记录已被删除,则不返回数据。

注意:begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个修改操作InnoDB表的语句,事务才真正启动,才会向mysql申请事务id,mysql内部是严格按照事务的启动顺序来分配事务id的。
总结:
MVCC机制的实现就是通过read-view机制与undo版本链比对机制,使得不同的事务会根据数据版本链对比规则读取
同一条数据在版本链上的不同版本数据。
Innodb引擎SQL执行的BufferPool缓存机制
在Innodb存储引擎中,Mysql设计了一个Buffer Pool存储池,一条sql的实际操作的其实就是这个存储池。例如,当一条update语句执行时,在Mysql中大致有以下几个步骤:
1、从ibd文件中加载被更新数据所在的数据页上的一整页数据到Buffer Pool中。
2、写入原始数据到undo日志中。
3、更新Buffer Pool中的数据。
4、写redo日志到Redo Buffer。
5、准备提交事务,redo日志写入磁盘。
6、准备提交事务,binlog日志写入磁盘。
7、写入commit标记到redo日志文件中,提交事务完成。
8、更新磁盘数据。
上面有几个新的概念:
redo日志:这个日志文件是用来恢复Buffer Pool存储池的。当DB重启时,会将这个文件中的数据加载到缓冲池。如果db在重启时,存在数据未更新到磁盘,这个时候会继续执行上面的第8步。
binlog日志:这个日志文件是用来恢复磁盘数据的。如果数据库ibd文件被人删了,可以通过这个这个日志文件来恢复。
那为什么Mysql不能直接更新磁盘上的数据而且设置这么一套复杂的机制来执行SQL呢?
简单来说,就是因为对ibd文件的写操作是随机的,而对redolog操作是顺序的。顺序的I/O比随机的I/O性能高几个数量级。
末尾附上诸葛老师的SQL执行流程图

Mysql锁与MVCC机制相关推荐

  1. MySQL - 多版本控制 MVCC 机制初探

    文章目录 生猛干货 MVCC (Multi-Version Concurrency Control)原理 快照读与当前读 MVCC 多版本实现 总结 搞定MySQL 生猛干货 带你搞定MySQL实战, ...

  2. MySQL 锁与MVCC :数据库的锁、MVCC、当前读、快照读、锁算法、死锁

    文章目录 lock与latch 锁的类型 MVCC 一致性非锁定读(快照读) 一致性锁定读(当前读) 锁算法 死锁 锁升级 lock与latch 在了解数据库锁之前,首先就要区分开lock和latch ...

  3. 认真学习MySQL中的MVCC机制

    什么是MVCC?MVCC(Multiversion Concurrency Control),多版本并发控制.顾名思义,MVCC是通过数据行的多个版本管理来实现数据库的并发控制.这项技术使得在Inno ...

  4. Mysql事务隔离MVCC机制

    MVCC是Mysql保证可重复读和读已提交两个级别的隔离性用到的一套机制,串行化执行是通过加锁来实现的,而MVCC机制下在对同一行数据进行读和写时,不会直接加锁互斥. MVCC主要由undo日志版本链 ...

  5. mysql中的mvcc机制

    MVCC多版本并发控制 简述MySQL锁 在InnoDB引擎下,按锁的粒度分类,可以分为行锁和表锁. 行锁实际上是作用在索引之上的.当我们的SQL命中了索引,那锁住的就是命中条件内的索引节点(这就是行 ...

  6. 面试系列MySql:谈谈MVCC机制的理解

    介绍 MVCC全称是: Multiversion concurrency control,多版本并发控制,提供并发访问数据库时,对事务内读取的到的内存做处理,用来避免写操作堵塞读操作的并发问题. 举例 ...

  7. mysql 锁机制 mvcc_轻松理解MYSQL MVCC 实现机制

    轻松理解MYSQL MVCC 实现机制 轻松理解MYSQL MVCC 实现机制 #### 1. MVCC简介 ##### 1.1 什么是MVCC MVCC是一种多版本并发控制机制. ##### 1.2 ...

  8. MySQL中MVCC+行级锁的工作机制(源码佐证)

    转自:https://blog.csdn.net/Waves___/article/details/105295060 序 最近在学习MySQL中的MVCC,看了网上的各种版本,什么创建版本号.删除版 ...

  9. mysql锁机制——乐观锁、悲观锁;共享锁、排他锁、行表锁、间隔后码锁、MVCC 与 thinkphp的lock解析

    锁的引入 如果A有100元,同时对B.C转账,若处理是同时的,则此时同时读取A的余额为100元,在对两人转账后写回,A的余额不是0元而是50元.因此,为了防止这种现象的出现,要引入锁的概念,如只有在A ...

最新文章

  1. 详细解析ASP.NET中Request接收参数乱码原理
  2. [原创]浅谈持续集成在测试中的应用
  3. Windows 命名管道 + 异步I/O模型
  4. 什么时候该用MySQL,什么时候该用ES呢?
  5. 推荐一些国产开源项目
  6. 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 21丨报告系统状态的连续日期【难度困难】​
  7. 设计模式学习笔记——策略(Strategy)模式
  8. ajax中get请求url传参数
  9. 关于Go1.14,你一定想知道的性能提升与新特性
  10. 拓端tecdat|SAS中用单因素ANOVA研究不同疗法对焦虑症的有效性
  11. java实现进制转换
  12. redis px nx ex xx
  13. .NET in China - What's New in .NET
  14. php实现微信第三方登录
  15. 老域名及用户行为习惯.
  16. 【信息安全】数据安全与信息安全
  17. 移卡参投的乐享互动首日破发:旗下乐刷罚单不断,逾期率高居不下
  18. AI趋势下,小布助手的进化论
  19. 赵匡胤为何不把皇位传给儿子却传弟弟赵光义
  20. DDD为什么能火起来?DDD 与微服务到底是啥关系!

热门文章

  1. KCF跟踪算法论文阅读与原理分析
  2. pythonturtle颜色大全_python turtle 有多少可用颜色?
  3. cocos2d-x飞机大战——飞机移动的动画效果
  4. 《杨澜访谈录》逐风者第三季 |数字技术把教育引向未来
  5. 最实用的web前端开发知识框架图
  6. 用unity shaderlab 实现「影之诗」中的闪卡特效(一)
  7. 7个机械键盘、21个小度音箱、28本技术书籍免费送!
  8. 幼师转行成为产品经理,入行月薪13K!
  9. CF1025B 题解
  10. Google发布AutoDraw堪称美术缺陷者的上帝之手