MySQL技术内幕InnoDB存储引擎(七)——事务
什么是数据库的事务?
事务是访问并更新数据库中各种数据的一个程序执行单元。事务也是数据库区别于文件系统的一个重要特性。
事务需要满足的特性
1.原子性
原子性就是指数据库中的一个完整的事务是不可分割的工作单位。要么都成功,要么都失败,不能执行一部分。
2.一致性
一致性指事务将数据库从一种状态转变为下一种一致的状态。
所谓一致性状态,就是数据库的数据满足约束的要求。
3.隔离性
事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离,也就是一个事务提交对其他事务不可见,可以用锁来实现。
4.持久性
持久性就是事务提交后的结果是永久的,如果发送宕机,也能将数据进行恢复。
持久性保证事务系统的高可靠性,而不是高可用性。高可靠性就是指连续可以正常工作的时间,可用性是指单位时间内,可用的时间比。
事务的分类
1.扁平事务
所有操作都处于同一层次,而且操作是原子的,要么都执行,要么都回滚。
特点:
- 是事务类型最简单的一种,也是实际生产环境中最频繁的事务。
- 不能提交或者回滚事务的某一个部分,或者几个步骤提交。
2.带有保存点的扁平事务
和扁平事务的不同点就是允许事务在执行过程中回滚到该事务之前的一个状态点。
保存点:用来通知系统应该记住事务当前的状态,以便之后能够回到保存点时的状态。一个事务中可以有很多个保存点。
3.链事务
是保存点模式的一种变种。将事务切分为多个串联的事务,当前事务提交之后,将处理的上下文再传给下一个事务,像一个链条一样,一环接一环。
目的: 为了解决保存点事务中,如果发生系统崩溃,保存点都消失的情况。这里将保存点都换成了事务提交,相当于在保存点就将事务提交了,这样就算宕机了,提交了的事务也不会损失。
问题: 链事务的回滚就只能在当前事务中了。所以需要将每个事务中的操作都减少一些。
4.嵌套事务
是一个层次结构框架,由一个顶层事务控制着各个层次的事务。
特点:
- 嵌套事务是由若干事务组成的一棵树,子树既可以是嵌套事务,也可以是扁平事务。
- 叶节点的事务是扁平事务。
- 在根节点的事务是顶层事务,其他事务都是子事务。
- 子事务可以提交也可以回滚,但是提交操作不会马上生效,要等到顶层事务提交才会真正提交。
- 任一事务的回滚都会引起其儿子的回滚。
5.分布式事务
在一个分布式环境下运行的扁平事务,因此需要根据数据所在位置访问网络中的不同节点。
事务的具体实现
在InnoDB上各个事务级别有其具体的实现方式:
- 锁:隔离性。
- redo log:原子性和持久性。
- undo long:一致性。
1. redo
什么是重做日志?
重做日志用来实现事务的持久性,也就是将产生一些数据库操作保存到日志。这些操作的特点是,其操作结果缓冲区中,并没有写到磁盘中。
重做日志的特点:
- 当触发事务提交时就需要先将该事务的所有日志写到重做日志中进行持久化。
- 重做日志是顺序写的。
如何确保重做日志的持久性?
为了确保每次日志都写入重做日志文件(磁盘),在每次将重做日志缓冲写入磁盘后,存储引擎都需要调用一次fsync操作(将内存数据写到磁盘)。所以,磁盘的性能决定了数据库的性能。
如何通过重做日志提高数据库性能?
用户可以设置重非持久性的情况发生。当事务提交的时候,不马上写入磁盘,而是等一个时间周期之后再执行fsync。这样可以优化日志的写入时间,从而提高数据库的性能。但是如果发生宕机,会丢失一部分未刷新的数据。
重做日志的存储方式
InnoDB的存储引擎中,重做日志缓存和重做日志文件以重做日志块的形式进程存储,一个块的大小为512字节。如果一个页的重做日志大于一个块能够存储的范围,则会被分割为多个块进行存储。
为什么是512字节呢? 因为磁盘的一个扇区大小512字节,可以保证原子性。
重做日志缓冲写到磁盘的触发条件:
- 事务提交时;
- 当日志缓冲的一半空间被使用;
- log checkpoint时。
重做日志恢复数据的原理:
- 不管上次数据库是否正常关闭,都会尝试进行恢复操作。
- checkpoint表示已经刷新到磁盘的日志序列号,所以,只需要恢复checkpoint之后的日志序列号的日志部分即可。
- 执行重做日志。
2.binlog
binlog也就是二进制文件,是数据库上层对已提交了的事务的SQL语句的记录。
binlog和redo log的区别:
- 二者表面上看都是记录了数据库操作的日志,但是本质上有着很大的不同。
- 重做日志是存储引擎层产生的,二进制日志是数据库的上层产生的。二进制日志不仅仅正对引擎层,数据库中任何的更改操作都会产生二进制日志。
- 两种日志记录的内容形式不同。二进制文件是操作逻辑上的,重做日志是物理格式上的。二进制文件对应SQL语句,而重做日志对应引擎对数据页得修改。
- 写入磁盘的时间点不同。二进制日志只在事务提交完成后进行一次写入,而InnoDB存储引擎的重做日志会不断地写入,不随事务提交的顺序影响。
3. undo
什么是undo日志?
用于事务的回滚操作。undo日志中记录了数据之前的版本,当执行回滚操作的时候,利用这些之前的数据信息即可修改到之前的样子。undo日志也用于版本控制(MVCC),当用户读取一行记录的时候,该记录已经被其他事务占用了,当前事务就可以根据事务隔离级别,读取过去相应版本的数据,实现非锁定读,提高并发性能。
undo日志会产生重做日志,因为undo日志也需要持久化。
undo日志的存储方式:
同样采用段的方式进行存储,每个回滚段中记录1024个undo日志段,而在每个undo日志段中进行undo页的申请。也就是undo日志是写入到undo日志段中的undo页。多个事务可以共享一个undo页。
4.purge
用于完成最终的delete和update操作。
当delete操作和update操作提交后,只是将相应记录的flag置为1,并没有删除或者修改记录,真正的操作会延时到purge操作来完成。
为什么需要这样设计,而不是直接操作?
当事务提交时,其他事务可能正在引用这行,如果直接删除会产生错误,所以,能不能删除,就需要purge操作进行判断。如果该技术已经不被其他事务引用,就可以进行真正的删除操作。这就优点像JVM垃圾回收判断机制。
5.group commit
什么是group commit?
顾名思义,就是写一堆数据到磁盘。每次事务提交都需要进行fsync操作,这样不能利用磁盘的效率,如果每次写入一组提交的数据,并进行写优化,减少磁盘IO次数,就能提高性能。
MySQL实现批量二进制日志提交的流程:
数据
- Flush阶段,将每个事务的二进制日志写入内存;
- Sync阶段,将内存中二进制文件写入磁盘,如果有多个事务,那么一次fsync操作就能完成日志写入;
- Cmmit阶段,队头事务根据顺序调用引擎层事务的提交。
事务的隔离级别
SQL标准定义的四个隔离级别:
- 读未提交:会脏读。
- 读已提交:会不可重复读。
- 可重复读:会幻读。
- 串行化:都不会
InnoDB事务隔离级别的特点: InnoDB的默认隔离级别是可重复读,其默认事务隔离级别是可重复读。它的可重复度级别下,通过Next-Key算法,避免了幻读。所以,InnoDB的可重复度就已经达到了串行化的隔离性要求。
分布式事务
什么是分布式事务?
是指允许多个独立的事务资源参与到一个全局的事务当中。
InnoDB提供了对XA事务的支持,并通过XA事务来支持分布式事务的实现。必须将隔离级别设置为串行化,才能使用分布式事务。
XA事务的实现原理
XA事务由一个或者多个资源管理、一个事务管理器和一个应用程序组成:
- 资源管理器:提供访问事务资源的方法。也就是数据库
- 事务管理器:协调参与全局事务的各个事务。就是链接数据库的客户端。
- 应用程序:定义事务的边界,指定全局事务中的操作。
分布式事务两段式提交方式
- 第一阶段,所有餐具全局事务的节点开始准备,告诉事务管理器它们准备好提交了。
- 第二阶段,事务管理器告诉资源管理器执行回滚还是提交。如果任何一个节点不能提交,其他节点都需要回滚。
不好的事务习惯
1.在循环中提交
如果在循环中提交,那么循环很大,就需要提交很多次,每次提交都要重做日志,这样就会大大增加开销。如果在循环最后提交,则只需要写一个重做日志,降低开销。
InnoDB存储引擎会默认自动提交。
2.使用自动提交
开发人员不能很好的掌控事务。应该把事务的控制权交给开发人员。
3.使用自动回滚
如果InnoDB在存储过程中发生错误会自动执行回滚操作。
使用自动回滚无法张掌控准确信息。
长事务
长事务就是执行时间较长的事务。
长事务一旦执行失败,就需要回滚,会造成很大的损失,所以,需要将其切分为很多给小事务。
MySQL技术内幕InnoDB存储引擎(七)——事务的更多相关文章
- (转)Mysql技术内幕InnoDB存储引擎-事务&备份&性能调优
事务 原文:http://yingminxing.com/mysql%E6%8A%80%E6%9C%AF%E5%86%85%E5%B9%95innodb%E5%AD%98%E5%82%A8%E5%BC ...
- 《mysql技术内幕 InnoDB存储引擎(第二版)》阅读笔记
一.mysql架构 mysql是一个单进程多线程架构的数据库. 二.存储引擎 InnoDB: 支持事务 行锁 读操作无锁 4种隔离级别,默认为repeatable 自适应hash索引 每张表的存储都是 ...
- Mysql技术内幕——InnoDB存储引擎
Mysql技术内幕——InnoDB存储引擎 http://jingyan.baidu.com/article/fedf07377c493f35ac89770c.html 一.mysql体系结构和存储引 ...
- mysql技术内幕InnoDB存储引擎-阅读笔记
mysql技术内幕InnoDB存储引擎这本书断断续续看了近10天左右,应该说作者有比较丰富的开发水平,在源码级别上分析的比较透彻.如果结合高可用mysql和高性能mysql来看或许效果会更好,可惜书太 ...
- MySQL技术内幕InnoDB存储引擎(三)——文件相关
构成MySQL数据库和InnoDB存储引擎表的文件类型有: 参数文件:MySQL实例运行时需要的参数就是存储在这里. 日志文件:用来记录MySQL实例对某种条件做出响应时写入的文件. socket文件 ...
- (转)Mysql技术内幕InnoDB存储引擎-表&索引算法和锁
表 原文:http://yingminxing.com/mysql%E6%8A%80%E6%9C%AF%E5%86%85%E5%B9%95innodb%E5%AD%98%E5%82%A8%E5%BC% ...
- MySQL技术内幕InnoDB存储引擎(表&索引算法和锁)
表 4.1.innodb存储引擎表类型 innodb表类似oracle的IOT表(索引聚集表-indexorganized table),在innodb表中每张表都会有一个主键,如果在创建表时没有显示 ...
- 《MySQL技术内幕 InnoDB存储引擎 》学习笔记
第1章 MySQL体系结构和存储引擎 1.3 MySQL存储引擎 数据库和文件系统最大的区别在于:数据库是支持事务的 InnoDB存储引擎: MySQL5.5.8之后默认的存储引擎,主要面向OLTP ...
- 【Mysql技术内幕InnoDB存储引擎】读书笔记
一.存储引擎 1.InnoDB引擎 设计目标是面向在线事务(OLTP)处理的应用. 支持事务.行级锁.通过多版本并发控制(MVCC)支持高并发.提供一致性非锁定读.next-key locking避免 ...
随机推荐
- 记录一次读取hdfs文件时出现的问题java.net.ConnectException: Connection refused
公司的hadoop集群是之前的同事搭建的,我(小白一个)在spark shell中读取hdfs上的文件时,执行以下指令 >>> word=sc.textFile("hdfs ...
- cephfs删除报nospace的问题
ceph Vol 45 Issue 2 CephFS: No space left on device After upgrading to 10.2.3 we frequently see mess ...
- ceph客户端服务端属性匹配关系
ceph的server是定期会发布版本,而它的客户端是放到linux 内核当中的,一些属性的支持是依赖于内核版本的,这样就存在一些问题,一些功能后端支持,而客户端旧了:还有可能是客户端用的很新的内核, ...
- time和random模块
# 时间模块 # 三种时间表现形式 # 时间戳 # 格式化的时间字符串 # 元组(struct_time)结构化时间 struct_time元组共有9个元素(年,月,日,时,分,秒,一年中的第几周,一 ...
- [原题复现+审计][BUUCTF 2018]WEB Online Tool(escapeshellarg和escapeshellcmd使用不当导致rce)
简介 原题复现:https://github.com/glzjin/buuctf_2018_online_tool (环境php5.6.40) 考察知识点:escapeshellarg和escap ...
- Nmap详解
扫描方式 -Pn/-P0:扫描前不用ping测试目标是否可达,默认所有目标端口都可达 -sT:TCP Connect扫描,进行完整的TCP三次握手,该类型扫描已被检测,且会在目标日志中记录大量连接请求 ...
- go编译成exe后,打开出现闪退问题
今天博主编译了一个go小脚本,编译完成后用自己电脑试了一下没有问题 然而,当换了一台电脑后,一样是win7系统64位,出现了闪退 于是乎博主疯狂百度 看到网上说 入口文件 的顶部改成 packa ...
- sqlilab less23-less27a
less23 本关过滤掉了注释符号-- 和#,并且变量带入数据库时被单引号包裹.需要将后边的单引号闭合.使用and '1'='1,将其加在注入语句的末尾,使用suffix参数 less-24 以后填坑 ...
- 一 HTML基础入门
HTML概念 HTML是标记语言,由W3C组织提供的一套标记标签组成.其使用标记标签来描述网页,一个网页除了由大量的标签组成,还有后续要学习的css样式和JavaScript脚本组合而成. 网页与网站 ...
- 你还在 if...else?代码这样写才好看!
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...