mysql提交事务_mysql事务的实现原理

此篇文章算是对mysql事务的一个总结,基本把mysql事务相关的知识点都涵盖到了,面试问来问去无非也就是这些,在了解这些之前我们先对mysql在执行的过程中有一个整体的认识,如下图

5992398067dca5db1494078c2ea4473f.png

如上图所示,MySQL服务器逻辑架构从上往下可以分为三层:

(1)第一层:处理客户端连接、授权认证等。

(2)第二层:服务器层,负责查询语句的解析、优化、缓存以及内置函数的实现、存储过程等。

(3)第三层:存储引擎,负责MySQL中数据的存储和提取。MySQL中服务器层不管理事务,事务是由存储引擎实现的。MySQL支持事务的存储引擎有InnoDB、NDB Cluster等,其中InnoDB的使用最为广泛;其他存储引擎不支持事务,如MyIsam、Memory等。

具体过程都在图中有所标注,大概看看有个认识就可以了。接下来咱们逐一总结

典型的MySQL事务是如下操作的:

start transaction;…… #一条或多条sql语句commit;

其中start transaction标识事务开始,commit提交事务,将执行结果写入到数据库。如果sql语句执行出现问题,会调用rollback,回滚所有已经执行成功的sql语句。当然,也可以在事务中直接使用rollback语句进行回滚。

自动提交

MySQL中默认采用的是自动提交(autocommit)模式,如下所示:

mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit | ON |+---------------+-------+1 row inset (0.00 sec)

在自动提交模式下,如果没有start transaction显式地开始一个事务,那么每个sql语句都会被当做一个事务执行提交操作。

通过如下方式,可以关闭autocommit;需要注意的是,autocommit参数是针对连接的,在一个连接中修改了参数,不会对其他连接产生影响。

mysql> set autocommit =0;Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit | OFF |+---------------+-------+1 row inset (0.00 sec)

如果关闭了autocommit,则所有的sql语句都在一个事务中,直到执行了commit或rollback,该事务结束,同时开始了另外一个事务。

特殊操作

在MySQL中,存在一些特殊的命令,如果在事务中执行了这些命令,会马上强制执行commit提交事务;如DDL语句(create table/drop table/alter/table)、lock tables语句等等。

不过,常用的select、insert、update和delete命令,都不会强制提交事务。

事务的特点:ACID

原子性(Atomicity)

「定义」

「实现原理」在说明原子性原理之前,首先介绍一下MySQL的事务日志。MySQL的日志有很多种,如二进制日志、错误日志、查询日志、慢查询日志等,此外InnoDB存储引擎还提供了两种事务日志:redo log(重做日志)和undo log(回滚日志)。其中redo log用于保证事务持久性;undo log则是事务原子性和隔离性实现的基础。

下面说回undo log。实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句。InnoDB实现回滚,靠的是undo log:当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

undo log属于逻辑日志,它记录的是sql执行相关的信息。当发生回滚时,InnoDB会根据undo log的内容做与之前相反的工作:对于每个insert,回滚时会执行delete;对于每个delete,回滚时会执行insert;对于每个update,回滚时会执行一个相反的update,把数据改回去。

以update操作为例:当事务执行update时,其生成的undo log中会包含被修改行的主键(以便知道修改了哪些行)、修改了哪些列、这些列在修改前后的值等信息,回滚时便可以使用这些信息将数据还原到update之前的状态。

6e20a51ed7cd9251b1bbc0c0149420f9.png

831e01a53bb549396fe75969bb89452c.png

从上图可以了解到数据的变更都伴随着回滚日志的产生:

(1) 产生了被修改前数据(zhangsan,1000) 的回滚日志

(2) 产生了被修改前数据(zhangsan,0) 的回滚日志

根据上面流程可以得出如下结论:

每条数据变更(insert/update/delete)操作都伴随一条undo log的生成,并且回滚日志必须先于数据持久化到磁盘上所谓的回滚就是根据回滚日志做逆向操作,比如delete的逆向操作为insert,insert的逆向操作为delete,update的逆向为update等。回滚过程如图

89934837ea6d8ae1b5c6e5ee35a805cf.png

tips:undo log也可以这么理解

当delete一条记录时,undo log中会记录一条对应的insert记录 当insert一条记录时,undo log中会记录一条对应的delete记录当update一条记录时,它记录一条对应相反的update记录

tips:逻辑日志和物理日志的区别看记日志的时候 是针对一行记录,就是逻辑日志 如果是一个数据页,就是物理日志

持久性(Durability)

「定义」

事务一旦提交,其所做的修改会永久保存到数据库中,此时即使系统崩溃修改的数据也不会丢失。

「实现原理:Redo log(WAL write ahead log)」

先了解一下MySQL的数据存储机制,MySQL的表数据是存放在磁盘上的,因此想要存取的时候都要经历磁盘IO,然而即使是使用SSD磁盘IO也是非常消耗性能的。

为此,为了提升性能InnoDB提供了缓冲池(Buffer Pool),Buffer Pool中包含了磁盘数据页的映射,可以当做缓存来使用:读数据:会首先从缓冲池中读取,如果缓冲池中没有,则从磁盘读取再放入缓冲池;

写数据:会首先写入缓冲池,缓冲池中的数据会定期同步到磁盘中(这一过程称为刷脏);

上面这种缓冲池的措施虽然在性能方面带来了质的飞跃,但是它也带来了新的问题,当MySQL系统宕机,断电的时候可能会丢数据!!!

因为我们的数据已经提交了,但此时是在缓冲池里头,还没来得及在磁盘持久化,所以我们急需一种机制需要存一下已提交事务的数据,为恢复数据使用。

于是redolog就派上用场了。下面看下redolog是什么时候产生的

47738da72234d0ef6925362ff319b63e.png

既然redo log也需要存储,也涉及磁盘IO为啥还用它?

(1)刷脏是随机IO,因为每次修改的数据位置随机,但写redo log是追加操作,属于顺序IO。

(2)刷脏是以数据页(Page)为单位的,MySQL默认页大小是16KB,一个Page上一个小修改都要整页写入;而redo log中只包含真正需要写入的部分,无效IO大大减少。

「redo log与binlog」

我们知道,在MySQL中还存在binlog(二进制日志)也可以记录写操作并用于数据的恢复,但二者是有着根本的不同的:

(1)作用不同:redo log是用于crash recovery的,保证MySQL宕机也不会影响持久性;binlog是用于point-in-time recovery的,保证服务器可以基于时间点恢复数据,此外binlog还用于主从复制。

(2)层次不同:redo log是InnoDB存储引擎实现的,而binlog是MySQL的服务器层(可以参考文章前面对MySQL逻辑架构的介绍)实现的,同时支持InnoDB和其他存储引擎。

(3)内容不同:redo log是物理日志,内容基于磁盘的Page;binlog的内容是二进制的,根据binlog_format参数的不同,可能基于sql语句、基于数据本身或者二者的混合。

(4)写入时机不同:binlog在事务提交时写入;redo log的写入时机相对多元:

前面曾提到:当事务提交时会调用fsync对redo log进行刷盘;这是默认情况下的策略,修改innodb_flush_log_at_trx_commit参数可以改变该策略,但事务的持久性将无法保证。除了事务提交时,还有其他刷盘时机:如master thread每秒刷盘一次redo log等,这样的好处是不一定要等到commit时刷盘,commit速度大大加快。

隔离性(Isolation)

「定义」

与原子性、持久性侧重于研究事务本身不同,隔离性研究的是不同事务之间的相互影响。隔离性是指,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。严格的隔离性,对应了事务隔离级别中的Serializable (可串行化),但实际应用中出于性能方面的考虑很少会使用可串行化。

「实现原理」

隔离性追求的是并发情形下事务之间互不干扰。简单起见,我们仅考虑最简单的读操作和写操作(暂时不考虑带锁读等特殊操作),那么隔离性的探讨,主要可以分为两个方面:

(一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性(一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性

「脏读、不可重复读和幻读」

首先来看并发情况下,读操作可能存在的三类问题:

脏读:当前事务(A)中可以读到其他事务(B)未提交的数据(脏数据),这种现象是脏读。举例如下(以账户余额表为例)

84b1dd50033481cc91b9c7176e510c56.png

不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据。举例如下:

ce73a38ba49d4cf040ae185408867c22.png

幻读:在事务A中按照某个条件先后两次查询数据库,两次查询结果的条数不同,这种现象称为幻读。不可重复读与幻读的区别可以通俗的理解为:前者是数据变了,后者是数据的行数变了。举例如下

2e3c7de9476dc6e898164eb8c13ce0e8.png

「事务隔离级别」

e5ed1a23b49b9d720b478c13d4e3f2bb.png

在实际应用中,读未提交在并发时会导致很多问题,而性能相对于其他隔离级别提高却很有限,因此使用较少。可串行化强制事务串行,并发效率很低,只有当对数据一致性要求极高且可以接受没有并发时使用,因此使用也较少。因此在大多数数据库系统中,默认的隔离级别是读已提交(如Oracle)或可重复读(后文简称RR)。可以通过如下两个命令分别查看隔离级别:

select @@tx_isolation;+-----------------+| @@tx_isolation |+-----------------+| REPEATABLE-READ |+-----------------+1 row inset (0.00 sec)

「MVCC」

RR解决脏读、不可重复读、幻读等问题,使用的是MVCC:MVCC全称Multi-VersionConcurrencyControl,即多版本的并发控制协议。下面的例子很好的体现了MVCC的特点:在同一时刻,不同的事务读取到的数据可能是不同的(即多版本)——在T5时刻,事务A和事务C可以读取到不同版本的数据。

a968df9f4d08cfb452922eff72408c61.png

MVCC最大的优点是读不加锁,因此读写不冲突,并发性能好。InnoDB实现MVCC,多个版本的数据可以共存,主要是依靠数据的隐藏列(也可以称之为标记位)和undo log。其中数据的隐藏列包括了该行数据的版本号、删除时间、指向undo log的指针等等;当读取数据时,MySQL可以通过隐藏列判断是否需要回滚并找到回滚需要的undo log,从而实现MVCC;隐藏列的详细格式不再展开。

下面结合前文提到的几个问题分别说明

「脏读」

8156889712c9b6278e8f6a87f88ba1a9.png

当事务A在T3时间节点读取zhangsan的余额时,会发现数据已被其他事务修改,且状态为未提交。此时事务A读取最新数据后,根据数据的undo log执行回滚操作,得到事务B修改前的数据,从而避免了脏读。

「不可重复读」

11fb548e396d51c83824eda31ff6cd68.png

当事务A在T2节点第一次读取数据时,会记录该数据的版本号(数据的版本号是以row为单位记录的),假设版本号为1;当事务B提交时,该行记录的版本号增加,假设版本号为2;当事务A在T5再一次读取数据时,发现数据的版本号(2)大于第一次读取时记录的版本号(1),因此会根据undo log执行回滚操作,得到版本号为1时的数据,从而实现了可重复读。

「幻读」

InnoDB实现的RR通过next-key lock机制避免了幻读现象。

next-keylock是行锁的一种,实现相当于recordlock(记录锁)+gaplock(间隙锁);其特点是不仅会锁住记录本身(recordlock的功能),还会锁定一个范围(gaplock的功能)。当然,这里我们讨论的是不加锁读:此时的next-keylock并不是真的加锁,只是为读取的数据增加了标记(标记内容包括数据的版本号等);准确起见姑且称之为类next-keylock机制。还是以前面的例子来说明:

e224e1a5e33f140ea50b62779f43f1fe.png

当事务A在T2节点第一次读取0

总结

概括来说,InnoDB实现的RR,通过锁机制、数据的隐藏列、undolog和类next-keylock,实现了一定程度的隔离性,可以满足大多数场景的需要。不过需要说明的是,RR虽然避免了幻读问题,但是毕竟不是Serializable,不能保证完全的隔离,下面是一个例子,大家可以自己验证一下。

9273a3112216254a535dc809dc4216b8.png

一致性

基本概念

一致性是指事务执行结束后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。数据库的完整性约束包括但不限于:实体完整性(如行的主键存在且唯一)、列完整性(如字段的类型、大小、长度要符合要求)、外键约束、用户自定义完整性(如转账前后,两个账户余额的和应该不变)。

实现

可以说,一致性是事务追求的最终目标:前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性。此外,除了数据库层面的保障,一致性的实现也需要应用层面进行保障。

实现一致性的措施包括:

保证原子性、持久性和隔离性,如果这些特性无法保证,事务的一致性也无法保证数据库本身提供保障,例如不允许向整形列插入字符串值、字符串长度不能超过列的限制等应用层面进行保障,例如如果转账操作只扣除转账者的余额,而没有增加接收者的余额,无论数据库实现的多么完美,也无法保证状态的一致

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/521171.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux Shell脚本专栏_查看网卡的实时流量_06

文章目录查看网卡的实时流量1. 脚本内容2. 运行脚本查看网卡的实时流量 一个服务器的流量基本可以评估出当前服务器的负载和业务的访问情况,这样更有利于对当前服务器一个大致的了解,这也是在日常的监控中这个流量是必不可少的! 本案例&…

MaxCompute 多租户数据安全体系

很多用户对MaxCompute多租户数据安全体系感兴趣,我们将对其进行系统介绍,主要包括如下内容: MaxCompute 用户认证MaxCompute 项目空间内的访问控制和权限管理MaxCompute 跨项目空间的访问控制和权限管理MaxCompute 常见错误解析 基本术语 p…

如果批评《说好不哭》不自由,则赞美周杰伦无意义

戳蓝字“CSDN云计算”关注我们哦!作者 | 朱小五and王小九责编 | 阿秃从前从前有个人爱你很久,但偏偏风渐渐把距离吹得好远。——《晴天》他来了,他来了,他带着新歌mv和跟他一样胖了一圈的阿信来了。周杰伦新歌《说好不哭》一上线…

面向云数据库,超低延迟文件系统PolarFS诞生了

随着国内首款Cloud Native自研数据库POLARDB精彩亮相ICDE 2018的同时,作为其核心支撑和使能平台的PolarFS文件系统的相关论文"PolarFS: An Ultra-low Latency and Failure Resilient Distributed File System for Shared Storage Cloud Database"也被数据…

Data Lake Analytics-数据分析时代迎来新变革

前言 近期阿里云重磅推出新的数据分析引擎Data Lake Analytics,Data Lake Analytics是Serverless化的交互式联邦查询服务。无需ETL,使用标准SQL即可分析与集成对象存储(OSS)、数据库(PostgreSQL/MySQL/SQL Server等)、NoSQL(TableStore等)数据源的数据。…

这款耳机堪比千元级的AirPods

你如果问我:生活中你觉得必不可少的一件电子产品是什么?那么我会毫不犹豫的回答你:是耳机!出门忘带耳机是绝对不能忍听不听没关系,但是有它比较安心我觉得生活中不仅是我很多人都对耳机有一种依赖因为很多人都喜欢音乐…

java 发送邮件_Jenkins实现自动化邮件发送踩坑记录

文章简介本文分享Jenkins实现邮件发送,安装Jenkins可参考jenkins安装。写这篇文章,是在实际使用Jenkins过程中遇到这样一个问题,当每次Jenkins构建成功或者失败后,需要个人登录Jenkins查看构建结果,同时在构建前做了数…

Linux Shell脚本专栏_监控100台服务器磁盘利用率脚本_07

文章目录监控100台服务器磁盘利用率脚本1. 远程连接生成sshkey2. 复制ssh公钥到目标服务器3. 登录目标服务器查看4. 私钥免登录5. 192.168.43.134 服务器创建host,info文件6. 编辑脚本7. 赋予可执行权限8. 运行脚本9. 命令分解监控100台服务器磁盘利用率脚本 1. df -h 查看磁盘…

在linux下安装python3_【转】在Linux下安装python3

原文链接:http://www.cnblogs.com/feng18/p/5854912.html1、linux下安装python3a、 准备编译环境(环境如果不对的话,可能遇到各种问题,比如wget无法下载https链接的文件)2 下载 Python3.5代码包wget https://www.python.org/ftp/python/3.5.0…

【举栗子】Docker 容器磁盘占满的几种情况 | CSDN博文精选

戳蓝字“CSDN云计算”关注我们哦!作者 | isea533转自 | CSDN博客责编 | 阿秃参考文档:https://docs.docker.com/engine/reference/commandline/dockerd/应用日志过多默认情况下,每个 Docker 容器都有 10G 的存储空间,…

下一代智能数据工厂,阿里云发布全新DataWorks

大数据的开发能力已经成为企业的核心竞争力之一, 企业对数据资产的管理、加工、利用的诉求也越来越强烈。 9月5日,阿里云发布了DataWorks V2版本, 可提升数据开发的效率并简化数据操作,为企业提供了安全可靠的一站式大数据智能云研发平台。 众所周知,企…

MaxCompute 项目空间内的访问控制和权限管理

项目空间内的访问控制分为以下五类: 用户管理ACL授权Policy授权角色管理基于标签的访问控制管理 用户管理 任意非项目空间Owner用户必须被加入MaxCompute项目空间中,并被授予相对应权限,方能操作MaxCompute中的数据、作业、资源及函数。示例…

mysql 中间点策略_网易MySQL中间件的负载均衡策略及性能优化

团队介绍网易乐得DBA组,负责网易乐得电商、网易邮箱、网易技术部数据库日常运维,负责数据库私有云平台的开发和维护,负责数据库及数据库中间件Cetus的开发和测试等等。一、背景随着业务的爆发式增长,电商系统中的读写压力越来越高…

华为与美国公司就授权5G平台展开初期谈判;Linux 中存在严重漏洞;Microsoft 发布 Cosmos DB GA 版……...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周两次,打卡即read更快、更全了解泛云圈精彩newsgo go go iPhone12 概念图&#xff08…

Bellman_Ford算法总结

知识概览 Bellman_Ford算法适合解决存在负权边的最短路问题,时间复杂度为O(nm)。在存在负权边的最短路问题中,Bellman_Ford算法的效率虽然不如SPFA算法,但是Bellman_Ford算法能解决SPFA算法不能解决的经过不超过k条边的最短路问题。 例题展示…

java collections_扫盲java.util.Collections工具包,学习排序、二分、洗牌、旋转算法

作者:小傅哥 博客:https://bugstack.cn沉淀、分享、成长,让自己和他人都能有所收获! 一、前言算法是数据结构的灵魂!好的算法搭配上合适的数据结构,可以让代码功能大大的提升效率。当然,算法学习…

如何进行MaxCompute 用户认证?

您可以通过以下两种方式进行用户认证。 检查请求Request发送者的真实身份 即请求发送后,参数包括用户名和密码,服务端会验证用户名和密码是否正确,以此判断Request发送者的身份是否可信。 使用此方法有可能在请求时间较长的情况下&#xf…

Linux Shell脚本专栏_MySQL数据库备份_09

文章目录一、MySQL数据库备份单循环1. 安装mysql2. 配置mysql环境变量3. 刷新环境变量4. 创建数据库和表lue5. 脚本制作6. 运行脚本7. 查看备份的sql文件7. 脚本升级动态传参8. 运行脚本9. 查看备份的sql文件二、MySQL数据库表备份多循环2.1. 脚本制作2.2. 运行脚本2.3. 指定目…

【当头棒喝】你是真的了解云计算吗?

戳蓝字“CSDN云计算”关注我们哦!作者 | 全球物联网观察责编 | 阿秃对于“云计算”这个名词,大家早已耳熟能详,而且出场率越来越高!但对于很多新入行的“小白”来说,其中涉及的各种概念可能令人毫无头绪,这…

专注数据,打造阿里云Elasticsearch“一站式”数据服务体系

众所周知,Elasticsearch的问世使得各种结构、非结构数据得以实现实时搜索、分析的可能,越来越多的用户使用ES集群(即Elasticseach集群,下文均简称ES集群)实现数据的升值与挖掘。而用户在开发的过程中总是面临数据导入、…