MySQL 什么是事务?
该文为《 MySQL 实战 45 讲》的学习笔记,感谢查看,如有错误,欢迎指正
一、事务简介
事务就是为了保证一组数据库操作,要么全部成功,要么全部失败。
事务是在引擎层实现的,也就是说并不是所有引擎都可以使用事务,MyISAM 就不支持事务,这也是为什么会被 InnoDB 取代的原因。
说到事务,就不得不说 ACID 特性(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)。
二、ACID 特性
2.1 原子性(Atomicity)
一个事务中的多组操作,要么全部成功,要么全部失败。在事务提交(commit)成功之后,所有的操作都生效,提交失败,所有的操作都会回滚。
2.2 一致性(Consistency)
一个事务执行之前和执行之后数据库都必须处于一致性状态。在事务执行的过程中,只要事务未提交,就不会改变数据库的状态。提交之后事务已完成,此时数据库状态发生变化。
2.3 隔离性(Isolation)
事务在执行过程中,是与外界完全隔离的,即使数据库发生了变更,事务中也获取不到。A 事务对数据库做的变更,在事务未提交之间,数据库中也看不到,B 事务中也看不到。
2.4 持久性(Durability)
事务一旦提交,对数据库的变更就会持久化到磁盘,即使数据库发生异常重启,数据也不会丢失。
三、隔离级别
当数据库出现有多个事务同时执行时,就可能出现脏读,幻读,不可重复读等问题,隔离级别就是为了解决这些问题的。隔离的越严实,效率就越低,并发越低,安全性越高。
隔离级别分为以下 4 种:
读未提交(read uncommitted,RU)
一个事务还未提交时,它做的变更就可以被别的事务看到。读提交(read committed,RC)
事务提交以后,它做的变更才能被其它事务看到。但是在这个事务未提交之前,数据库中发生的变更,这个事务也能看见。可重复度(repeatable read,RR)
事务总是只能看见在启动的那个时刻,数据库的状态。事务未提交之前做的变更,其它事务看不见。事务执行期间,数据库中已经发生的变更,这个事务也看不见。只能看见事务刚启动时刻,数据库的状态。串行化(serializable)
事务对某一行的操作会加锁,“写”会加“写锁”,“读”会加“读锁”,在锁释放掉之前,其它的事务都无法都这一行的记录进行操作。必须等之前的事务执行完毕,释放锁。后面的事务又会重新加锁。
我们通过一个例子来说明一下四种隔离级别具体是怎么体现的。
给出一个建表语句:
mysql> create table T(c int) engine=InnoDB;
mysql> insert into T(c) values(1);
假设有以下两个事务,其中执行的操作如图,从上至下是时间先后顺序:

在四种不同的隔离级别下,V1、V2、V3的值分别为多少呢?我们现在分析一下:
读未提交
读提交下,事务还未提交,做的变更就能被其它事务看见,因此事务 B 修改了值为 2 ,事务 A 可以直接看见。所以V1 = 2,V2 = 2,V3 = 2。读提交(RC)
读提交下,事务在提交之前,做的变更都无法被其它事务看见,但是事务本身可以看到数据库的变更。 因此,事务 B 做了修改以后,事务 A 无法立刻看见,V1 = 1,事务 B 提交以后,事务 A 就可以看到数据库的变更了,因此V2 = 2,V3 = 2。可重复读(RR)
事务总是只能看到在启动的那个时刻,数据库的状态,即在事务未提交之前,自己做的变更别的事务看不见,数据库中的变更自己也看不见。
因此,事务 B 提交之前,A 看不见 B 做的变更,V1 = 1,事务 B 提交以后,数据库的值虽然发生了变更,但是事务 A 还未提交,A 还是只能看到自己在启动时刻,数据库的值(可以理解为数据库有版本,只能看见历史版本)。因此,V2 = 1,事务 A 提交以后,就可以看到数据库的变更了,因此V3 = 2。串行化
串行化是指,事务在操作某一行记录时会加锁,“读”会加“读锁”,“写”会加“写锁”。
事务 A 在启动后,先执行了 1 条查询语句,对这行数据加了“读锁”,这个“读锁”要等事务 A 提交以后,才会释放。因此事务 B 执行查询语句会处于等待锁释放状态。这时候事务 B 会一直等待。因此,V1 = 1,V2 = 1,事务 A 提交之后,“读锁”释放,事务 B 获取该行记录的“读锁”,并更新了数据(又加了一个“写锁”),事务 B 未提交之前,A 再去查数据也需要等待锁释放,事务 B 提交以后,锁释放,A 拿到锁,开始查询数据,因此,V3 = 2。
以上是如何实现的呢?
四、事务隔离的实现原理
数据库中会创建一个视图,在“可重复读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。在“读提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的。这里需要注意的是,“读未提交”隔离级别下直接返回记录上的最新值,没有视图概念;而“串行化”隔离级别下直接用加锁的方式来避免并行访问。
在 MySQL 中,实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。
回滚日志什么时候删除呢,系统中没有比这个回滚日志更早的 read-view 时,这个回日志就会被删除。
因此不建议使用长事务,容易导致回滚日志太多,大量占用存储空间。
五、事务的启动方式
- 显式启动:
begin或start transaction。配套的提交语句是commit,回滚语句是rollback。 - 也可以使用
set autocommit=0,此时不需要显式启动,比如执行了一个select语句就直接启动了事务,但是需要再执行一条commit来提交;
因此建议设置set autocommit=1,此时需要用begin来开启事务,如果觉得多了一次交互,比较麻烦的话,也可以使用commit work and chain,表示提交当前事务,并且再启动一个新的事务,这样就只有一次begin了。
感谢阅读,有兴趣的小伙伴可以关注我的微信公众号DevOps探索之旅,大家一起学习进步

MySQL 什么是事务?的更多相关文章
- PHP mysql与mysqli事务详解
官方对PHP连接到MySQL数据库服务器的三种主要的API简介如下: http://php.net/manual/zh/mysqli.overview.php PHP mysql与mysqli事务详解 ...
- 【MySQL】漫谈MySQL中的事务及其实现
最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySQL,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...
- MySQL数据库的事务管理
当前在开发ERP系统,使用到的数据库为Mysql.下面介绍下如何开启事务,以及事务隔离的机制 : 1. 检查当前数据库使用的存储引擎. show engines; 2. 修改前my.ini中的文件如下 ...
- MySQL存储过程之事务管理
原文链接:http://hideto.iteye.com/blog/195275 MySQL存储过程之事务管理 ACID:Atomic.Consistent.Isolated.Durable 存储程序 ...
- MySQL数据库分布式事务XA优缺点与改进方案
1 MySQL 外部XA分析 1.1 作用分析 MySQL数据库外部XA可以用在分布式数据库代理层,实现对MySQL数据库的分布式事务支持,例如开源的代理工具:ameoba[4],网易的DDB,淘宝的 ...
- 漫谈MySql中的事务
最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySql,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...
- mysql中不同事务隔离级别下数据的显示效果--转载
事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都 ...
- 浅谈mysql中不同事务隔离级别下数据的显示效果
事务的概念 事 务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查 询语句因为崩溃或其他原因而无法执行,那 ...
- MySql中的事务嵌套
1.Mysql中的事务必须是InnoDB.Berkeley DB引擎,myisam不支持. 2.Mysql是不支持嵌套事务的,开启了一个事务的情况下,再开启一个事务,会隐式的提交上一个事务. 3.My ...
- MySQL中Procedure事务编写基础笔记
原文:MySQL中Procedure事务编写基础笔记 目录: 一.PROCEDURE: 二.CREATE PROCEDURE基本语法: 三.PROCEDURE小进阶 3.1.基本的DECLARE语 ...
随机推荐
- 19_07_8校内训练[sort]
题意 一个排列,每次选一个子序列按顺序放在开头,要求变成升序的操作次数不超过17次,给出方案.n<=1E5. 思考 对于ai=aj-1且i<j的数字,一定要保持其相对顺序.可以根据这个关系 ...
- [HNOI2008]明明的烦恼(prufer序列,高精度,质因数分解)
prufer序列 定义 Prufer数列是无根树的一种数列.在组合数学中,Prufer数列由有一个对于顶点标过号的树转化来的数列,点数为n的树转化来的Prufer数列长度为n-2. 描述 eg 将 ...
- Informatica9.5.1创建资源库出错找不到libpmora8.so
错误信息: Database driver event...Error occurred loading library [libclntsh.so.10.1: cannot open shared ...
- 前端入门nginx
一.nginx是什么 NGINX is a free, open-source, high-performance HTTP server and reverse proxy, as well as ...
- 曹工说Spring Boot源码(14)-- AspectJ的Load-Time-Weaving的两种实现方式细细讲解,以及怎么和Spring Instrumentation集成
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- linux 修改系统时间 同步网络时间
一.date命令 date -s time 修改系统时钟时间为time 设置时间和日期 例如:将系统日期设定成2018年6月8日的命令 命令 : "date -s 06/08/2018&q ...
- WeChall_ Training: Stegano I (Training, Stegano)
This is the most basic image stegano I can think of. 解题: 一张小图片,文本方式打开.
- wireshark抓包思维导图---新手推荐
- java8种基本数据类型
- C++ map通过key获取value
c++的map中通过key获取value的方法 一般是value =map[key],或者另一种迭代器的方式 1.在map中,由key查找value时,首先要判断map中是否包含key. 2.如果不 ...