上一篇我们了解了mysql的几种日志,大致知道这些日志的作用,今天我们配合Mysql的事务以及事务的隔离级别进一步理解mysql如何实现事务相关的特性。其中重点理解mysql innodb的多版本控制和乐观锁,这篇大部分是文字描述,也是理解mysql-innodb事务的基础内容,也是面试会问到的内容。

事务的特征ACID

原子性:事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。上一篇我们知道 redo log 用于保证事务持久性,是因为每次数据变更,mysql都会先记录redo log,然后更新到数据页的缓存,然后在刷到磁盘中;那mysql是如何实现原子性的呢,首先理解原子性,就是一组操作单元,要么全部执行成功,要么不执行,我们在做分布式的系统的时候,就会涉及到分布式的事务,两个分布式操作,要么都成功,要么都失败,所有的操作都需要回滚到最初的状态,我们所了解有XA协议规则,XA是比较老的分布式事务基础,它的核心思路是基于两阶段提交的方式,第一阶段,数据准备,然后锁住资源,第二步才会提交。今天我们不讨论分布式事务的方案,这里不做深入研究,大家可以了解一下两阶段和TCC三阶段,以及Base定理和CAP定理。好了,言归正传,我们从工作中的场景,来反向思考,mysql的事务是如何实现的呢?对于一个事务如何保证这些语句最终能保证原子性呢?上一篇讲到了redolog 和binlog的一致性方案,就涉及到两阶段提交的方式来保证一致性。这里要讲的是Mysql的undo log,它是保证事务的原子性和隔离性的基础。

我们知道mysql事务中只要对数据修改的,都会生成相应的undo日志,1.对于每个 insert,这会往undo日志插入一条对应的删除语句,回滚时会执行 delete2.对于每个 delete,回滚时会执行 insert。3.对于每个 update,回滚时会执行一个相反的 update,把数据改回去。以 update 操作为例:当事务执行 update 时,其生成的 undo log 中会包含被修改行的主键(以便知道修改了哪些行)、修改了哪些列、这些列在修改前后的值等信息,回滚时便可以使用这些信息将数据还原到 update 之前的状态。

一致性:在事务开始和完成时,数据都必须保持一致状态,保持数据的完整性。其实这里说的一致性,如果原子性保证了,mysql的数据库的数据就会更新成功,失败则回滚到原来的状态,所以一致性其实是基于事务的原子性和持久性下,一致性就自然而然就得到了保证。

1.事务执行成功,redo日志和binlog日志就是持久性保障2.事务执行失败则, undo log则是事务原子性的保障,他担负这回滚的任务。

隔离性:数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。隔离性则是多事务并行操作下,保证各个事务之间独立运行相互隔离的,不受其他事务影响的特性。持久性:事务完成之后,它对于数据的修改是永久性的,它是原子性和一致性保证的前提下。

数据库隔离级别

Mysql-innodb可以通过设置mysql的事务隔离级别,全局修改,修改mysql.ini配置文件,在最后加上transaction-isolation = REPEATABLE-READ,#可选参数有:读未提交READ-UNCOMMITTED,读已提交:READ-COMMITTED, 可重复读:REPEATABLE-READ, 串行化:SERIALIZABLE

1.读未提交:就是在并发事务中,可以读到没有提交的事务变更数据;2.读已提交:读到已经提交的事务变更记录;3.可重复读:mysql的innodb默认的事务隔离级别,每次查询一条记录的时候,每个事务都会创建不同的读视图read-view,所以在该事务下,都会读对应的视图,如果有三个事务,每一个事务都有自己读到的最新数据的视图,所以在事务中,每次读到的都是一开始数据的快照版本,这就是mysql的多版本并发控制,下面会详细介绍mysql的MVCC。4.串行化:是最高的事务隔离级别,没开启一个事务,都是串行的,每一个事务都会对相应的数据行加锁来保证串行,这样一个事务结束,才能开启下一个事务,这样就完全保证了事务直接的隔离性。一般情况下并不会设置该隔离级别。

为什么要有可重读的隔离级别

我们知道数据库操作的时候,它是不断更新的,如果说我一个事务,开始执行的时候,我只想用到当前已有记录,不管是否已经更新,或者追加 或者减少,我都希望我当前操作是我事务开始的快照,不管是否发生变化,这样,可重复读就可以满足我们的需求,不管我是查询,还是更新,删除 已提交的事务,我都不喜欢看到原来的数据有变化。这就是实际开发中,我们为了防止出现幻读的情况。

可重复读的实现

上面说了,可重复读隔离级别下,数据库会为我们创建相应的read-view快照,事务中的所有操作都会基于这个快照版本。还有mysql实现了MVCC的并发访问控制的机制,那么什么是MVCC呢?首先这里我选择直接查看官方文档,这样理解起来是最原始的资料,以免自己陷入不同的blog解说版本,可能不利于自己分析问题。

[Mysql5.5官方开发文档中MVCC解释]

1.介绍

nnoDB是一个多版本存储引擎:它保存有关已更改行的旧版本的信息,以支持并发和回滚等事务功能。此信息存储在表空间中称为回滚段的数据结构中(在Oracle中的类似数据结构之后)。InnoDB使用回滚段中的信息来执行事务回滚中所需的撤消操作。 它还使用该信息构建行的早期版本以进行一致读取。

2.MVCC多版本的实现方案

InnoDB为存储在数据库中的每一行添加三个字段。6字节的DB_TRX_ID字段指示插入或更新该行的最后一个事务的事务标识符 。此外,删除在内部被视为更新,其中行中的特殊位被设置为将其标记为已删除 每行还包含一个7字节的DB_ROLL_PTR字段,称为滚动指针。 roll指针指向写入回滚段的撤消日志记录。如果更新了行,则撤消日志记录包含在更新行之前重建行内容所需的信息。6字节的DB_ROW_ID字段包含在插入新行时单调增加的行ID。 如果InnoDB自动生成聚簇索引,则索引包含行ID值。否则,DB_ROW_ID列不会出现在任何索引中。

DATA_TRX_ID 标记了最新更新这条行记录的transaction id,每处理一个事务,其值自动+1DATA_ROLL_PTR 指向当前记录项的rollback segment的undo log记录,找之前版本的数据就是通过这个指针DB_ROW_ID,当由innodb自动产生聚集索引时,聚集索引包括这个DB_ROW_ID的值,否则聚集索引中不包括这个值.,这个用于索引当中DELETE BIT位用于标识该记录是否被删除,这里的不是真正的删除数据,而是标志出来的删除。真正意义的删除是在commit的时候。这个字段 在官方文档中没有,但是很多博客中有出现,可能是在5.5之后的版本才加上的。

3.undo日志如何产生和销毁:

回滚段中的undo log分为插入和更新撤消日志。 只在事务回滚中才需要插入undo日志,并且可以在事务提交后立即丢弃。更新undo log也用于一致性读取,但只有在InnoDB没有分配快照的事务之后才能丢弃它们,在一致读取中可能需要更新撤消日志中的信息来构建早期版本的 数据库行。

4.长事务问题

按时提交你的事务,包括那些只发出一致读取的事务。 否则,InnoDB无法丢弃更新撤消日志中的数据,并且回滚段可能会变得太大,从而填满了表空间。回滚段中撤消日志记录的物理大小通常小于相应的插入或更新行。 您可以使用此信息计算回滚段所需的空间。这个问题,也就说明了我们尽量不要使用长事务,长时间不提交,导致回滚段日志变得很大,导致mysql数据库不可用。

5.删除记录时,MVCC的实现机制

在InnoDB多版本控制方案中,当您使用SQL语句删除行时,不会立即从数据库中物理删除该行。InnoDB在丢弃为删除写入的更新undo log记录时,仅物理删除相应的行及其索引记录。此删除操作称为清除,并且速度非常快,通常与执行删除的SQL语句的时间顺序相同。

高性能Mysql

下面是《高性能Mysql》中寻找一下MVCC的相关解释,发现和官方版本就是并不一致,它是以更加简化的思路来阐述MVCC的版本控制,我们也可以解读一下。

1.mvcc是行级锁的一个变种,它为了避免直接加锁,性能更好,2.实现是通过保存数据某个时间点的快照3.innodb中的MVCC通过在每行的记录后面保存两个隐藏的列来实现的,(1).一个是保存创建行的系统创建版本号,每开启一个事务,该版本号就会自增,这系统版本号作为事务的版本号,用来查询和定位多事务的隔离版本(2).另一个字段就是行的过期时间或者删除时间。备注:这里隐藏的列其实和官方开发文档dev中的描述有相似的地方,作者这里只是简单描述MVCC的工作原理,所以具体的我们还是以官方文档为准。4.MVCC只会在可重复读和读提交的隔离级别下工作,因为读未提交的数据就是读的最新的数据行,串行化是通过加锁。

乐观锁和MVCC 是一件事吗?

通过上面的分析,我们是否有一种错觉,MVCC不就是实现的乐观锁的功能吗,我们是不是开发的时候不需要再考虑Mysql的乐观锁问题。一般的我们在并发中,涉及到更新操作时,都会再where条件加上对应的版本信息(比如时间戳,具体的变更字段状态等),这里最好还是使用时间戳,比较好,因为我们系统数据设计的时候都会有modifyDate字段,状态或者其他值,可能存在ABA问题,当然几率很小。这就是我们乐观锁的实现。上面说到MVCC,每次事务都会有MVCC保证可重复读,并且有隐藏的版本控制,我们是不是就可以不用乐观锁了呢?这里,我有必要说一下,虽然MVCC有乐观并发控制的意思,它只是控制了事务中该记录的版本,然后事务读到始终是快照版本而已,并没有做事务提交时版本的判断,所以我们还是要手动的进行乐观锁的判断。并且拿到更新int结果为1,或者是预期值时才认为更新成功,否则需要做回滚。

小结

今天学习了mysql的ACID的实现原理,和事务隔离级别中的可重复读的实现机制MVCC,加深了事务的理解,如果上述阐述的有问题,或者不对的地方,欢迎留言指正和讨论。

微信公众号:MyClass社区

如有问题或建议,请公众号留言。

喜欢请关注

innodb下的mvcc_Mysql事务隔离以及MVCC实现原理相关推荐

  1. mininet编程实现交换机规则的插入、删除与修改。_Mysql事务隔离以及MVCC实现原理...

    上一篇我们了解了mysql的几种日志,大致知道这些日志的作用,今天我们配合Mysql的事务以及事务的隔离级别进一步理解mysql如何实现事务相关的特性.其中重点理解mysql innodb的多版本控制 ...

  2. InnoDB的几种事务隔离级别

    前文 首先理解事务的ACID的隔离性 并发带来的问题,脏读 .不可重复读 .幻读 的问题. 脏读: 一个事务读取了另一个事务未提交的数据,导致数据不一致.[事务2未提交] 不可重复读: 一个事务前后两 ...

  3. java innodb存储引擎_MySQL InnoDB存储引擎的事务隔离级别

    我们知道,在关系数据库标准中有四个事务隔离级别:未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据 提交读(Read Committed):只能读取 ...

  4. MySQL事务——事务隔离界别,MVCC

    目录 MySQL事务 事务隔离级别 事务的特性 并发事务引发的问题 事务的隔离级别 Read View在MVCC中的工作过程 可重复读的工作过程 读提交的工作过程 幻读的解决 MySQL事务 事务能够 ...

  5. mysql 事务隔离级别实现原理_MySQL事务隔离级别和实现原理 - 米扑博客

    开发中经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗, 事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢? MySQL 事务 本文所说的 MySQL 事务都是指在 InnoDB 引 ...

  6. MySQL事务隔离级别以及实现原理

    一.事务完整性问题 脏读:可以读取其他事务未提交的数据,如果该事务回滚,则数据为错误数据. 不可重复读:A事务查看,B事务修改提交,A事务再次查看,数据不一样. 幻读:幻读与不可重复读相似,但不可重复 ...

  7. MySQL事务隔离级别和实现原理

    经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗,事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢?本文就帮大家梳理一下. MySQL 事务 本文所说的 MySQL 事务都是指在 I ...

  8. 一文讲清楚MySQL事务隔离级别和实现原理,后台开发人员必备知识

    经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗,事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢?本文就帮大家梳理一下. MySQL 事务 本文所说的 MySQL 事务都是指在 I ...

  9. mysql事务隔离级别及实现原理

    mysql事务 Markdown编辑器用的不顺手,自己选的,跪着也要用完.        事务通俗的来讲就是SQL要么全部执行成功,要么全部执行失败回滚到执行前的状态.不存在部分执行成功,部分执行失败 ...

  10. 【Mysql】Mysql事务隔离界别及其实现原理

    文章目录 1.持久性 2.原子性 3.一致性 4.隔离性 (1)写写操作--锁 (2)写读(脏读,不可重复读,幻读)操作--MVCC 1.持久性 1.每次操作除了更新到buffer中,还会记录在red ...

最新文章

  1. 【bzoj1853】[Scoi2010]幸运数字 容斥原理+搜索
  2. monocross 环境搭建:MonoTouch Mono for Android
  3. 教你如何玩转redis-简单消息队列
  4. android+proguard目录,Android Proguard 详解
  5. 9月21日云栖精选夜读 | 如何优雅地从四个方面加深对深度学习的理解
  6. 一、从零创建VUE项目
  7. Eclipse里选择Servlet Run As Server后,自动生成了哪些资源?
  8. 基于tensorflow2.0利用CNN与线性回归两种方法实现手写数字识别
  9. AWS Lambda现已支持.NET Core 2.0
  10. ssl提高组周六模拟赛【2018.9.23】
  11. 在Ubuntu环境下使用vcpkg安装sqlite_orm包文件
  12. maven 添加本地库
  13. self-trainning, co-trainning
  14. 电子表格和oracle,##请问数据库和电子表格之间有什么区别
  15. 机器视觉——计算视野的小工具
  16. 陆振波的svm的matlab代码的解释,陆振波SVM的MATLAB代码解释
  17. OBS-RTMP推流
  18. 计算机前沿科学与发展,《数据与计算发展前沿》正式创刊
  19. 使用meshBaker合并多个mesh进行优化
  20. php 分页样式css样式,thinkphp5分页CSS样式代码

热门文章

  1. (转)关于oracle表空间的规划方法
  2. 再述:python中redis的使用(Pool)
  3. 【晒出你的第83行代码】跬步千里,十二年的老代码更是技术的沉淀!
  4. VS2015搭建live555源码调试环境
  5. MYSQL 大数据性能优化
  6. sessionFactory.getCurrentSession()的引出
  7. 终于有机会获得百度SEO的邀请码了
  8. 2008 DHCP中继器代理服务
  9. Linux系统攻略关于vi替换命令的使用说明
  10. 网络安全隐患,中国应发展自已的核心技术