MySQL事务原理浅析
前言
因为自己对数据的可靠性,可用性方面特别感兴趣,所以在MySQL事务方面看了很多资料,也看了很多博客,所以想到自己也写一篇博客整理整理自己所学内容,尽量用自己的语言解释得通俗易懂。
事务经典场景
在很多介绍事务的博客都会代入这样一个场景,先简单说说:
A给B转账100,A少100,B多100。如果A少100后系统崩溃怎么办?B的钱多不了,这样金钱总数凭空少了100。这里就需要用到事务了。
什么是事务?
事务是恢复和并发控制的基本单位,事务有四个特性(ACID),原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)。本文主要围绕这四个特性展开介绍。
原子性
原子性就是不可拆分的特性,要么全部成功然后提交(commit),要么全部失败然后回滚(rollback)。若开启事务,在上述场景就不会出现 A少100 成功,B多100 失败 这种情况。MySQL通过Redo Log重做日志实现了原子性,在将执行SQL语句时,会先写入redo log buffer,再执行SQL语句,若SQL语句执行出错就会根据redo log buffer中的记录来执行回滚操作,由此拥有原子性。
一致性
一致性指事务将数据库从一种状态转变为下一种一致的状态。比如有一个字段name有唯一索引约束,那么在事务前后都不能有重复的name出现违反唯一索引约束,否则回滚。在上述场景中即金钱总数总是200,不能凭空增加减少。MySQL通过undo Log实现一致性,执行SQL语句时,会先写入undo log再写入 redo log buffer。undo是逻辑日志,会根据之前的SQL语句进行相应回滚,比如之前是insert那么回滚时会执行一个delete,一个update会执行 一个相反的update。并且除了回滚,undo log还有一个作用是MVCC,当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可通过undo读取之前的行版本信息,实现非锁定读取。并且undo log也会产生redo log,因为undo log也需要持久性的保护。
隔离性
首先介绍如果没有隔离性会发生的4种情况
丢失更新
A事务撤销时,把已经提交的B事务的更新数据覆盖了。这种错误可能造成很严重的问题,通过下面的账户取款转账就可以看出来,MySQL通过三级封锁协议的第一级解决了丢失更新,事务 T 要修改数据 A 时必须加 X 锁,直到 T 结束才释放锁。
| 时间 | 取款事务A | 转账事务B |
|---|---|---|
| T1 | 开始事务 | |
| T2 | 开始事务 | |
| T3 | 查询账户余额为1000元 | |
| T4 | 查询账户余额为1000元 | |
| T5 | 汇入100元把余额改为1100元 | |
| T6 | 提交事务 | |
| T7 | 取出100元把余额改为900元 | |
| T8 | 撤销事务 | |
| T9 | 余额恢复为1000 元(丢失更新) |
脏读
脏读主要是读取到了其他事务的数据,而其他事务随后发生回滚。MySQL通过三级封锁协议的第二级解决了脏读,在一级的基础上,要求读取数据 A 时必须加 S 锁,读取完马上释放 S 锁。
| 时间 | 取款事务A | 转账事务B |
|---|---|---|
| T1 | 开始事务 | |
| T2 | 开始事务 | |
| T3 | 查询账户余额为1000元 | |
| T4 | ||
| T5 | 汇入100元把余额改为1100元 | |
| T6 | 查询账户余额为1100元(脏读) | |
| T7 | 撤销事务 | |
| T8 | 汇入100元以为是1200元 |
不可重复读
不可重复读是读取到数据后,随后其他事务对数据发生了修改,无法再次读取。MySQL通过三级封锁协议的第三级解决了不可重复读。在二级的基础上,要求读取数据 A 时必须加 S 锁,直到事务结束了才能释放 S 锁。
| 时间 | 取款事务A | 转账事务B |
|---|---|---|
| T1 | 开始事务 | |
| T2 | 开始事务 | |
| T3 | 查询账户余额为1000元 | |
| T4 | ||
| T5 | 汇入100元把余额改为1100元 | |
| T6 | 查询账户余额为1100元(不可重复读) | |
| T7 | 提交事务 | |
| T8 | 提交事务 |
幻读
幻读是读取到数据后,随后其他事务对数据发生了新增,无法再次读取。在InnoDB引擎Repeatable Read的隔离级别下,MySQL通过Next-Key Lock以及MVCC解决了幻读,事务中分为当前读以及快照读。
1.快照读(snapshot read) ——通过MVCC来避免幻读
简单的select操作(不包括 select … lock in share mode, select … for update)
2.当前读(current read) ——通过Next-Key Lock 来避免幻读 Next-Key Lock即间隙锁(Gap Lock)+行锁 (Record Lock)
select … lock in share mode
select … for update
insert
update
delete
| *时间* | 取款事务A | 转账事务B |
|---|---|---|
| T1 | 开始事务 | |
| T2 | 开始事务 | |
| T3 | 查询账户余额为1000元 RMB 100元美元 | |
| T4 | ||
| T5 | 汇入100欧元 | |
| T6 | 查询账户余额为1000元 RMB 100元美元 100欧元(幻读) | |
| T7 | 提交事务 | |
| T8 | 提交事务 |
事务有四个隔离级别
Read Uncommitted
解决了丢失更新
Read Committed
解决了丢失更新+脏读
Repeatable Read
解决了丢失更新+脏读+不可重复读 (Innodb下也解决了幻读,原理上文已说明)
Serializable
解决了丢失更新+脏读+不可重复读+幻读
从上至下,性能越差,安全性越优。
持久性
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。具体实现原理就是在事务commit之前会将,redo log buffer中的数据持久化到硬盘中的redo log file,这样在commit的时候,硬盘中已经有了我们修改或新增的数据,由此做到持久化。
总结
简单总结了一下MySQL事务,对于Redo Undo没有做到了如指掌的掌握所以介绍篇幅不太大,随着学习深入以后会进行相应补充。
参考资料
—–《MySQL技术内幕 InnoDB存储引擎》 第2版
MySQL事务原理浅析的更多相关文章
- mysql事务原理及MVCC
mysql事务原理及MVCC 事务是数据库最为重要的机制之一,凡是使用过数据库的人,都了解数据库的事务机制,也对ACID四个 基本特性如数家珍.但是聊起事务或者ACID的底层实现原理,往往言之不详,不 ...
- mysql事务原理以及锁
一.Innodb事务原理 1.什么是事务 a.事务(Transaction)是数据库区别于文件系统的重要特性之一,事务会把数据库从一种一致性状态转换为另一种一致性状态. b.在数据库提交时,可以确保要 ...
- 详解MySQL事务原理
老刘是即将找工作的研究生,自学大数据开发,一路走来,感慨颇深,网上大数据的资料良莠不齐,于是想写一份详细的大数据开发指南.这份指南把大数据的[基础知识][框架分析][源码理解]都用自己的话描述出来,让 ...
- 数据库篇:mysql事务原理之MVCC视图+锁
前言 数据库的事务特性 数据并发读写时遇到的一致性问题 mysql事务的隔离级别 MVCC的实现原理 锁和隔离级别 关注公众号,一起交流,微信搜一搜: 潜行前行 1 数据库的事务特性 原子性:同一个事 ...
- MySQL事务原理&实战【官方精译】
事务隔离级别 事务隔离是数据库处理的基础之一.隔离是I中的首字母 ACID ; 隔离级别是在多个事务同时进行更改和执行查询时,对结果的性能和可靠性,一致性和可重复性之间的平衡进行微调的设置. Inno ...
- Mysql事务原理介绍
事务 一个事务会涉及到大量的cpu计算和IO操作,这些操作被打包成一个执行单元,要么同时都完成,要么同时都不完成. 事务是一组原子性的sql命令或者说是一个独立的工作单元,如果数据库引擎能够成功的对数 ...
- Mysql事务原理
一.什么是事务 事务:是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作:这些操作作为一个整体一起向系统提交,要么都执行.要么都不执行:事务是一组不可再分割的操作集合(工作逻辑单元): ...
- Mysql—事务原理与详解
事务的四大特性 事务的隔离级别 https://www.cnblogs.com/57rongjielong/p/8036418.html https://blog.csdn.net/zwq123211 ...
- 浅析Mysql InnoDB存储引擎事务原理
浅析Mysql InnoDB存储引擎事务原理 大神:http://blog.csdn.net/tangkund3218/article/details/47904021
随机推荐
- P2P模式
P2P模式 P2P模式包含三个角色:消息队列(Queue),发送者(Sender),接收者(Receiver).每个消息都被发送到一个特定的队列,接收者从队列中获取消息.队列保留着消息,直到他们被消费 ...
- 在Android Studio中下载Android SDK的两种方式(Android Studio3.0、windows)
方式一:网站下载:https://androidsdkmanager.azurewebsites.net/SDKPlatform 方式二.设置HTTP Proxy1. 打开Settings2. 点击H ...
- Android 调用WCF实例详解
上篇文章已经对Web Service及其相关知识进行了介绍(Android开发之WebService介绍 ),相信有的朋友已经忍耐不住想试试在Android应用中调用Web Service.本文将通过 ...
- windows下安装node【转】
windows下安装node报错2503.2502 windows下命令行安装,首先使用管理员权限获取cmd msiexec /package node-v10.16.0-x64.msi 根据提示一步 ...
- php cURL error 60: SSL certificate problem: unable to get local issuer certificate 解决办法
错误例子如下: php5.6以上的版本会出现这种问题 关于“SSL证书问题:无法获取本地颁发者证书”错误.很明显,这适用于发送CURL请求的系统(并且没有服务器接收请求) 1)从https://cur ...
- 123457123456#0#----com.tym.ErTongFanPai20--前拼后广--儿童FanPai_tym
com.tym.ErTongFanPai20--前拼后广--儿童FanPai_tym
- ABAP DMEO 通过工单号读取内部对象号
*&---------------------------------------------------------------------* *& Report YDEMO_013 ...
- 简单明了的注解,读取CLASS中的注解
/***********注解声明***************/ /** * 水果名称注解 * @author peida * */ @Target(ElementType.FIELD) @Reten ...
- 【JS新手教程】JS获取当前星期几的几种方法
该文通过获取星期几的几种方法,介绍JS里的数组,判断,和字符串截取,可以当作新手教程看,小白也看的懂.获取星期几,可通过Date()对象的getDay()获取,获取的是一个数字,对应的是0,1,2,3 ...
- 【python基础】使用import导入相对路径的源文件
前言 在编写python代码的过程中,不同路径下的源码文件该如何引用,这是个问题,本文针对这个问题介绍解决方法. 源码目录结构: . ├── conf.py ├── main.py ├── mod/ ...