上一篇我们了解了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社区

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

喜欢请关注

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

  1. mininet编程实现交换机规则的插入、删除与修改。_Mysql闲聊之从Redo、Undo日志到MVCC实现原理

    文章大纲 Undo日志 Redo日志 MVCC Undo 日志 关系型数据需要实现事务的 ACID 特性,其中一点就是事务的原子性,Mysql 就是通过 Undo 日志就来实现的. 数据库处理数据都是 ...

  2. mininet编程实现交换机规则的插入、删除与修改。_可编程网卡芯片在滴滴云网络的应用实践...

    桔妹导读:随着云规模不断扩大以及业务层面对延迟.带宽的要求越来越高,采用DPDK 加速网络报文处理的方式在横向纵向扩展都出现了局限性.可编程芯片成为业界热点.本文主要讲述了可编程网卡芯片在滴滴云网络中 ...

  3. Access SQL语法(查询/插入/删除/连接/修改)

    SQL语法 1. 查询 简单查询 select 班级,姓名,性别 from 学生名单 加筛选条件 select 班级,姓名,性别 from 学生名单 where 性别="女" 分组 ...

  4. sybase 事务插入时不可查询_InnoDB事务与锁

    事务 可以理解为数据库执行的一个最基础的单位,其包含有限的操作命令(crud). 事务的属性(ACID):事务必须满足四个属性,原子性(atomicity).一致性(consistency).隔离性( ...

  5. iptables规则的查看、添加、插入、删除和修改

    1.查看 iptables -nvL –line-number -L 查看当前表的所有规则,默认查看的是filter表,如果要查看NAT表,可以加上-t NAT参数 -n 不对ip地址进行反查,加上这 ...

  6. iptables规则的查看、添加、删除和修改

    1.查看 iptables -nvL --line-number -L 查看当前表的所有规则,默认查看的是filter表,如果要查看NAT表,可以加上-t NAT参数 -n 不对ip地址进行反查,加上 ...

  7. 进程句柄表初始化,扩展,插入删除句柄源码分析

    一.为什么要有句柄 句柄是一个8字节的结构体,用途是指向内核对象.3环程序无法通过地址直接访问内核对象,所以需要用句柄来间接访问. 本文重点介绍句柄表,句柄本身则留到下一篇博客介绍.但因为接下来介绍句 ...

  8. firewalld/iptables防火墙维护和状态查询命令(防火墙重载,区域操作命令,开启服务或端口,堵塞端口,iptables规则添加和删除)

    文章目录 firewalld防火墙维护和状态查询命令 firewalld防火墙状态查询命令 firewalld防火墙重载配置命令 重新加载firewalld的配置 查询预定义信息命令 firewall ...

  9. Mininet系列实验(六):Mininet动态改变转发规则实验

    Mininet系列实验(六):Mininet动态改变转发规则实验 一. 实验目的 熟悉Mininet自定义拓扑脚本的编写: 熟悉编写POX脚本动态改变转发规则 二.实验原理 在SDN环境中,控制器可以 ...

最新文章

  1. 网络推广外包——网络推广外包指出新站上线前一定要做好自我检测
  2. ios - 使用@try、catch捕获异常:
  3. 总结一下F#中运算符的定义规则
  4. 黑马程序员pink老师前端入门教程,零基础必看的h5(html5)+css3+移动端前端视频教程(CSS3)
  5. Django 3.2.5博客开发教程:HelloWorld欢迎页面
  6. HDU4267(2012年长春站)
  7. http://www.tldp.org/LDP/abs/abs-guide.txt.gz
  8. 流式计算storm核心组件介绍以及入门案例---跟着就能在本地跑起来的storm项目
  9. ubuntu 14.04安装mysql数据库
  10. Linux 基本命令(九)--vim 常用命令
  11. python linux调试_linux怎么调试python
  12. RabbitMQ系列8 TTL 死信队列 延迟队列
  13. win7触摸板怎么关闭_笔记本电脑触摸板快速关闭,避免误碰影响操作
  14. Java解析多种文件输出字符串以及图片(ppt、odc、odcx、pptx、xls、xlsx、rtf)
  15. 我们手指触碰屏幕都做了什么?
  16. 电脑能连接热点和网线,不能连接WIFI
  17. Html id 选择器
  18. correl函数相关系数大小意义_在EXCEL中用“CORREL”函数求 两列的相关系数为什么是等于1?...
  19. 下载 https://github.com/android 上的全部源代码
  20. Unity 交通系统

热门文章

  1. Python爬取大量数据时,如何防止IP被封
  2. pycharm 波浪线报绿 Typo: In word 'xxxx'(绿色波浪线)
  3. Intel Realsense D435 composite_frame类 frame类 video_frame类 depth_frame类的关系
  4. mysql 生明变量_MySql中的变量定义
  5. 根据历史数据预测未来数据_未来销量预测——Kaggle基础方案(一):赛题背景和数据字段分析...
  6. springcloud ribbon retryTemplate操作流程分析
  7. idea没法识别java文件,idea文件左下角有个j的符号并是黄色
  8. git中的删除命令操作
  9. ueditor配置文件配置自动段落缩进_vimrc里各种配置的含义
  10. 定时器和promise_Promise面试题,控制异步流程