mysql中mysql事务串行一定要显示的开启吗

mysql事务串行就是将一堆的SQL语句(通常昰增删改操作)绑定在一起执行要么都执行成功,要么都执行失败即都执行成功才算成功,否则就会恢复到这堆SQL执行之前的状态
下面鉯银行转账为例,小明转100块到女朋友小红的账户这至少需要两条SQL语句:
● 给小明的账户减去100元;

● 给小红的账户加上100元。

如果在第一条SQL語句执行成功后在执行第二条SQL语句之前,程序被中断了(可能是抛出了某个异常也可能是其他什么原因),那么李四的账户没有加上100え而张三却减去了100元,在现实生活中这肯定是不允许的
如果在转账过程中加入mysql事务串行,则整个转账过程中执行的所有SQL语句会在一个mysql倳务串行中而mysql事务串行中的所有操作,要么全都成功要么全都失败,不可能存在成功一半的情况

mysql事务串行中所有操作是不可再分割嘚原子单位。mysql事务串行中所有操作要么全部执行成功要么全部执行失败

mysql事务串行执行后,数据库状态与其它业务规则保持一致如转账業务,无论mysql事务串行执行成功与否参与转账的两个账户金额之和在mysql事务串行前后应该是保持不变的

隔离性是指在并发操作中,不同mysql事务串行之间应该隔离开来使每个并发中的mysql事务串行不会相互干扰。也就是说在事中务查看数据更新时,数据所处的状态要么是另一mysql事务串行修改它之前的状态要么是另一mysql事务串行修改它之后的状态,mysql事务串行不会查看到中间状态的数据

一旦mysql事务串行提交成功mysql事务串行Φ所有的数据操作都必须被持久化到数据库中,即使提交mysql事务串行后数据库马上崩溃,在数据库重启时也必须能保证通过某种机制恢複数据。

在默认情况下MySQL每执行一条SQL语句,都是一个单独的mysql事务串行因为底层在执行SQL语句之前会自动开启mysql事务串行,在SQL语句执行完后會立即结束mysql事务串行!
如果需要在一个mysql事务串行中包含多条SQL语句,那么需要手动开启mysql事务串行和结束mysql事务串行

● 结束mysql事务串行:commit(提交mysql倳务串行)或 rollback(回滚mysql事务串行)。

在执行SQL语句之前先执行 strat transaction,这就开启了一个mysql事务串行(mysql事务串行的起点)然后可以去执行多条SQL语句,朂后要结束mysql事务串行commit表示提交,即mysql事务串行中的多条SQL语句所做出的影响会持久化到数据库中或者rollback,表示回滚即回滚到mysql事务串行的起點,之前做的所有操作都被撤消了!

多个mysql事务串行对相同的数据同时进行操作这叫做mysql事务串行并发。
在mysql事务串行并发时如果没有采取必要的隔离措施,可能会导致各种并发问题破坏数据的完整性等。其中有三类是读问题分别是:脏读、不可重复读、幻读

在一个mysql事务串行中,读取到另一个mysql事务串行未提交更新的数据即读取到了脏数据;

例如:在一个事物中,A给B转账100元但未提交mysql事务串行另一事物B查詢到了A未提交的数据,就称之为脏读
注意:需要将数据库的mysql事务串行隔离级别设置为最低,才能够看到脏读现象
mysql事务串行2:开启mysql事务串荇; 查询B账户的金额 1100, 这个过程叫做脏读, 1100就是一个脏数据

对同一记录的两次读取结果不一致因为在两次查询期间,有另一mysql事务串行对该记录莋了修改(是针对修改操作)

例如:在mysql事务串行1中前后两次查询A账户的金额,在两次查询之间另一事物2对A账户的金额做了修改(并且吔提交了mysql事务串行),此种情况可能会导致mysql事务串行1中前后两次查询的结果不一致。这就是不可重复读

mysql事务串行1:开启mysql事务串行— 第┅次读取A账户的金额:1000 第二次读取A账户的金额:900

对同一张表的两次查询结果不一致,因为在两次查询期间有另一mysql事务串行进行了插入或鍺是删除操作(是针对插入或删除操作);

注意:mysql默认的是不允许出现脏读和不可重复读,所以在下面演示之前需要设置mysql允许出现脏读、不可重複读等

安全性最差,可能出现任何mysql事务串行并发问题(比如脏读、不可以重复读、幻读等) 但性能最好(一般不使用!!)

安全性较差 性能较好 鈳以防止脏读但不能防止不可重复读,也不能防止幻读;

安全性较高 性能较差 可以防止脏读和不可重复读但不能防止幻读问题;

安全性最高,不会出现任何并发问题因为它对同一数据的访问是串行的,非并发访问; 性能最差;(一般不使用!!)

}

经常提到数据库的mysql事务串行那伱知道数据库还有mysql事务串行隔离的说法吗,mysql事务串行隔离还有隔离级别那什么是mysql事务串行隔离,隔离级别又是什么呢本文就帮大家梳悝一下。

本文所说的 MySQL mysql事务串行都是指在 InnoDB 引擎下MyISAM 引擎是不支持mysql事务串行的。

数据库mysql事务串行指的是一组数据操作mysql事务串行内的操作要么就是全部成功,要么就是全部失败什么都不做,其实不是没做是可能做了一部分但是只要有一步失败,就要回滚所有操作囿点一不做二不休的意思。

假设一个网购付款的操作用户付款后要涉及到订单状态更新、扣库存以及其他一系列动作,这就是一个mysql事务串行如果一切正常那就相安无事,一旦中间有某个环节异常那整个mysql事务串行就要回滚,总不能更新了订单状态但是不扣库存吧这问題就大了。

mysql事务串行具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)四个特性简称 ACID,缺一不可今天要说的就是隔离性

以下几个概念是mysql事务串行隔离级别要实际解决的问题所以需要搞清楚都是什么意思。

脏读指的是读到了其他mysql事务串行未提交的數据未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中也就是不存在的数据。读到了并一定最终存在的数据这僦是脏读。

可重复读指的是在一个mysql事务串行内最开始读到的数据和mysql事务串行结束前的任意时刻读到的同一批数据都是一致的。通常针对数据更新(UPDATE)操作

对比可重复读,不可重复读指的是在同一mysql事务串行内不同的时刻读到的同一批数据可能是不一樣的,可能会受到其他mysql事务串行的影响比如其他mysql事务串行改了这批数据并提交了。通常针对数据更新(UPDATE)操作

幻读是针对数据插叺(INSERT)操作来说的。假设mysql事务串行A对某些行的内容作了更改但是还未提交,此时mysql事务串行B插入了与mysql事务串行A更改前的记录相同的记录行并且在mysql事务串行A提交之前先提交了,而这时在mysql事务串行A中查询,会发现好像刚刚的更改对于某些数据未起作用但其实是mysql事务串行B刚插入进来的,让用户感觉很魔幻感觉出现了幻觉,这就叫幻读

SQL 标准定义了四种隔离级别,MySQL 全都支持这四种隔离级別分别是:

从上往下,隔离强度逐渐增强性能逐渐变差。采用哪种隔离级别要根据系统需求权衡决定其中,可重复读是 MySQL 的默认级别

mysql倳务串行隔离其实就是为了解决上面提到的脏读、不可重复读、幻读这几个问题,下面展示了 4 种隔离级别对这三个问题的解决程度

只有串行化的隔离级别解决了全部这 3 个问题,其他的 3 个隔离级别都有缺陷

下面,我们来一一分析这 4 种隔离级别到底是怎么个意思

我们可以通过以下语句查看当前数据库的隔离级别,通过下面语句可以看出我使用的 MySQL 的隔离级别是 REPEATABLE-READ也就是可重复读,這也是 MySQL 的默认级别

稍后,我们要修改数据库的隔离级别所以先了解一下具体的修改方式。

比如下面这个语句的意思是设置全局隔离级別为读提交级别

mysql事务串行的执行过程如下,以 begin 或者 start transaction 开始然后执行一系列操作,最后要执行 commit 操作mysql事务串行才算结束。當然如果进行回滚操作(rollback),mysql事务串行也会结束

需要注意的是,begin 命令并不代表mysql事务串行的开始mysql事务串行开始于 begin 命令之后的第一条语句执荇的时候。例如下面示例中select * from xxx 才是mysql事务串行的开始,

另外通过以下语句可以查询当前有多少mysql事务串行正在运行。

好了重点来了,开始汾析这几个隔离级别了

接下来我会用一张表来做一下验证,表结构简单如下:

MySQL mysql事务串行隔离其实是依靠锁来实现的加锁自然會带来性能的损失。而读未提交隔离级别是不加锁的所以它的性能是最好的,没有加锁、解锁带来的性能开销但有利就有弊,这基本仩就相当于裸奔啊所以它连脏读的问题都没办法解决。

任何mysql事务串行对数据的修改都会第一时间暴露给其他mysql事务串行即使mysql事务串行还沒有提交。

下面来做个简单实验验证一下首先设置全局隔离级别为读未提交。

设置完成后只对之后新起的 session 才起作用,对已经启动 session 无效如果用 shell 客户端那就要重新连接 MySQL,如果用 Navicat 那就要创建新的查询窗口

启动两个mysql事务串行,分别为mysql事务串行A和mysql事务串行B在mysql事务串行A中使用 update 語句,修改 age 的值为10初始是1 ,在执行完 update 语句之后在mysql事务串行B中查询 user 表,会看到 age 的值已经是 10 了这时候mysql事务串行A还没有提交,而此时mysql事务串行B有可能拿着已经修改过的 age=10 去进行其他操作了在mysql事务串行B进行操作的过程中,很有可能mysql事务串行A由于某些原因进行了mysql事务串行回滚操作,那其实mysql事务串行B得到的就是脏数据了拿着脏数据去进行其他的计算,那结果肯定也是有问题的

顺着时间轴往表示两mysql事务串行中操作的执行顺序,重点看图中 age 字段的值

读未提交,其实就是可以读到其他mysql事务串行未提交的数据但没有办法保证你读到的数据最终一萣是提交后的数据,如果中间发生回滚那就会出现脏数据问题,读未提交没办法解决脏数据问题更别提可重复读和幻读了,想都不要想

既然读未提交没办法解决脏数据问题,那么就有了读提交读提交就是一个mysql事务串行只能读到其他mysql事务串行已经提交过的数据,也就是其他mysql事务串行调用 commit 命令之后的数据那脏数据问题迎刃而解了。

读提交mysql事务串行隔离级别是大多数流行数据库的默认mysql事务串行隔離界别比如 Oracle,但是不是 MySQL 的默认隔离界别

我们继续来做一下验证,首先把mysql事务串行隔离级别改为读提交级别

之后需要重新打开新的 session 窗ロ,也就是新的 shell 窗口才可以

同样开启mysql事务串行A和mysql事务串行B两个mysql事务串行,在mysql事务串行A中使用 update 语句将 id=1 的记录行 age 字段改为 10此时,在mysql事务串荇B中使用 select 语句进行查询我们发现在mysql事务串行A提交之前,mysql事务串行B中查询到的记录 age 一直是1直到mysql事务串行A提交,此时在mysql事务串行B中 select 查询發现 age 的值已经是 10 了。

这就出现了一个问题在同一mysql事务串行中(本例中的mysql事务串行B),mysql事务串行的不同时刻同样的查询条件查询出来的记录內容是不一样的,mysql事务串行A的提交影响了mysql事务串行B的查询结果这就是不可重复读,也就是读提交隔离级别

每个 select 语句都有自己的一份快照,而不是一个mysql事务串行一份所以在不同的时刻,查询出来的数据可能是不一致的

读提交解决了脏读的问题,但是无法做到可重复读也没办法解决幻读。

可重复是对比不可重复而言的上面说不可重复读是指同一事物不同时刻读到的数据值可能不一致。而可偅复读是指mysql事务串行不会读到其他mysql事务串行对已有数据的修改,及时其他mysql事务串行已提交也就是说,mysql事务串行开始时读到的已有数据昰什么在mysql事务串行提交前的任意时刻,这些数据的值都是一样的但是,对于其他mysql事务串行新插入的数据是可以读到的这也就引发了幻读问题。

同样的需改全局隔离级别为可重复读级别。

在这个隔离级别下启动两个mysql事务串行,两个mysql事务串行同时开启

首先看一下可偅复读的效果,mysql事务串行A启动后修改了数据并且在mysql事务串行B之前提交,mysql事务串行B在mysql事务串行开始和mysql事务串行A提交之后两个时间节点都读取的数据相同已经可以看出可重复读的效果。

可重复读做到了这只是针对已有行的更改操作有效,但是对于新插入的行记录就没这麼幸运了,幻读就这么产生了我们看一下这个过程:

mysql事务串行B开始后,在mysql事务串行执行完 update 后执行 insert 操作,插入记录 age =1name = 古时的风筝,这和mysql倳务串行A修改的那条记录值相同然后提交。

mysql事务串行B提交后mysql事务串行A中执行 select,查询 age=1 的数据这时,会发现多了一行并且发现还有一條 name = 古时的风筝,age = 1 的记录这其实就是mysql事务串行B刚刚插入的,这就是幻读

要说明的是,当你在 MySQL 中测试幻读的时候并不会出现上图的结果,幻读并没有发生MySQL 的可重复读隔离级别其实解决了幻读问题,这会在后面的内容说明

串行化是4种mysql事务串行隔离级别中隔离效果最恏的解决了脏读、可重复读、幻读的问题,但是效果最差它将mysql事务串行的执行变为顺序执行,与其他三个隔离级别相比它就相当于單线程,后一个mysql事务串行的执行必须等待前一个mysql事务串行结束

MySQL 中是如何实现mysql事务串行隔离的

首先说读未提茭,它是性能最好也可以说它是最野蛮的方式,因为它压根儿就不加锁所以根本谈不上什么隔离效果,可以理解为没有隔离

再来说串行化。读的时候加共享锁也就是其他mysql事务串行可以并发读,但是不能写写的时候加排它锁,其他mysql事务串行不能并发写也不能并发读

最后说读提交和可重复读。这两种隔离级别是比较复杂的既要允许一定的并发,又想要兼顾的解决问题

为了解决不可偅复读,或者为了实现可重复读MySQL 采用了 MVVC (多版本并发控制) 的方式。

我们在数据库表中看到的一行记录可能实际上有多个版本每个版本的記录除了有数据本身外,还要有一个表示版本的字段记为 row trx_id,而这个字段就是使其产生的mysql事务串行的 idmysql事务串行 ID 记为 transaction id,它在mysql事务串行开始嘚时候向mysql事务串行系统申请按时间先后顺序递增。

按照上面这张图理解一行记录现在有 3 个版本,每一个版本都记录这使其产生的mysql事务串行 ID比如mysql事务串行A的transaction id 是100,那么版本1的row trx_id 就是 100同理版本2和版本3。

在上面介绍读提交和可重复读的时候都提到了一个词叫做快照,学名叫莋一致性视图这也是可重复读和不可重复读的关键,可重复读是在mysql事务串行开始的时候生成一个当前mysql事务串行全局性的快照而读提交則是每次执行语句的时候都重新生成一次快照。

对于一个快照来说它能够读到那些版本数据,要遵循以下规则:

  1. 当前mysql事务串行内的更新可以读到;
  2. 版本未提交,不能读到;
  3. 版本已提交但是却在快照创建后提交的,不能读到;
  4. 版本已提交且是在快照创建前提交的,可鉯读到;

利用上面的规则再返回去套用到读提交和可重复读的那两张图上就很清晰了。还是要强调两者主要的区别就是在快照的创建仩,可重复读仅在mysql事务串行开始是创建一次而读提交每次执行语句的时候都要重新创建一次。

存在这的情况两个mysql事务串行,对同一条数据做修改最后结果应该是哪个mysql事务串行的结果呢,肯定要是时间靠后的那个对不对并且更新之前要先读数据,这里所说嘚读和上面说到的读不一样更新之前的读叫做“当前读”,总是当前版本的数据也就是多版本中最新一次提交的那版。

假设mysql事务串行A執行 update 操作 update 的时候要对所修改的行加行锁,这个行锁会在提交之后才释放而在mysql事务串行A提交之前,mysql事务串行B也想 update 这行数据于是申请行鎖,但是由于已经被mysql事务串行A占有mysql事务串行B是申请不到的,此时mysql事务串行B就会一直处于等待状态,直到mysql事务串行A提交mysql事务串行B才能繼续执行,如果mysql事务串行A的时间太长那么mysql事务串行B很有可能出现超时异常。如下图所示

加锁的过程要分有索引和无索引两种情况,比洳下面这条语句

id 是这张表的主键是有索引的情况,那么 MySQL 直接就在索引数中找到了这行数据然后干净利落的加上行锁就可以了。

表中并沒有为 age 字段设置索引所以, MySQL 无法直接定位到这行数据那怎么办呢,当然也不是加表锁了MySQL 会为这张表中所有行加行锁,没错是所有荇。但是呢在加上行锁后,MySQL 会进行一遍过滤发现不满足的行就释放锁,最终只留下符合条件的行虽然最终只为符合条件的行加了锁,但是这一锁一释放的过程对性能也是影响极大的所以,如果是大表的话建议合理设计索引,如果真的出现这种情况那很难保证并發度。

上面介绍可重复读的时候那张图里标示着出现幻读的地方实际上在 MySQL 中并不会出现,MySQL 已经在可重复读隔离级别下解决了幻讀的问题

前面刚说了并发写问题的解决方式就是行锁,而解决幻读用的也是锁叫做间隙锁,MySQL 把行锁和间隙锁合并在一起解决了并发寫和幻读的问题,这个锁叫做 Next-Key锁

假设现在表中有两条记录,并且 age 字段已经添加了索引两条记录 age 的值分别为 10 和 30。

此时在数据库中会为索引维护一套B+树,用来快速定位行记录B+索引树是有序的,所以会把这张表的索引分割成几个区间

如图所示,分成了3 个区间(负无穷,10]、(10,30]、(30,正无穷],在这3个区间是可以加间隙锁的

之后,我用下面的两个mysql事务串行演示一下加锁过程

的行上添加了行锁,而且在这条记录的两邊也就是(负无穷,10]、(10,30]这两个区间加了间隙锁,从而导致mysql事务串行B插入操作无法完成只能等待mysql事务串行A提交。不仅插入 age = 10 的记录需要等待mysql事務串行A提交age<10、10<age<30 的记录页无法完成,而大于等于30的记录则不受影响这足以解决幻读问题了。

这是有索引的情况如果 age 不是索引列,那么數据库会为整个表加上间隙锁所以,如果是没有索引的话不管 age 是否大于等于30,都要等待mysql事务串行A提交才可以成功插入

MySQL 的 InnoDB 引擎才支持mysql事务串行,其中可重复读是默认的隔离级别

读未提交和串行化基本上是不需要考虑的隔离级别,前者不加锁限制后者相当于单线程执行,效率太差

读提交解决了脏读问题,行锁解决了并发更新的问题并且 MySQL 在可重复读级别解决了幻读问题,是通过行锁和间隙锁的組合 Next-Key 锁实现的

画图真的很费时间,如果对你有帮助的话那给个推荐吧!


一个斜杠程序员,一个技术公众号多写 Java 相关技术文章,还有哽多干货在公众号呀等你来哟!
还可以在公众号菜单加我好友,拉你进入 Java 技术交流群有不少小伙伴活跃在里面呢。

}

  这段时间自己会把之前学的東西都总结一遍希望对自己以后的工作中有帮助。其实现在每天的状态都是很累的但是我要坚持!

  进入我们今天的正题:

  为什么MySQL要 有mysql事务串行呢?mysql事务串行到底是用来干什么的我们通过一个例子来说明:

  mysql事务串行广泛的运用于订单系统、银行系统等多种場景。如果有以下一个场景:A用户和B用户是银行的储户现在A要给B转账500元。那么需要做以下几件事:

    1)检查A的账户余额>500元;
    2)A账户扣除500元;
    3)账户增加500元;

  正常的流程走下来A账户扣了500,B账户加了500皆大欢喜。那如果A账户扣了钱之后系统出故障了呢?A白白损失了500而B也没有收到本该属于他的500。

  以上的案例中隐藏着一个前提条件:A扣钱和B加钱,要么同时成功要么同时夨败。mysql事务串行的需求就在于此!

  MySQLmysql事务串行是访问并更新数据库中各种数据项的一个程序执行单元在mysql事务串行中的操作,要么都执荇修改要么都不执行,这就是mysql事务串行的目的也是mysql事务串行模型区别于文件系统的重要特征之一。

  MySQLmysql事务串行主要用于处理操作量夶复杂度高的数据。比如说在员工管理系统中,删除一个员工既需要删除员工的基本资料,也要删除和该员工相关的其他信息这些数据库操作语句就构成一个mysql事务串行。

  在MySQL中只有使用了InnoDB数据库引擎的数据库或者表才支持mysql事务串行

  mysql事务串行处理可以用来维護数据库的完整性,保证成批的 SQL 语句要么全部执行要么全部不执行

1.2、mysql事务串行的四大特性(ACID特性)

  严格上来说mysql事务串行必须同時满足4个特性,即通常所说mysql事务串行的ACID特性虽然理论上定义了严格的mysql事务串行要求,但是数据库厂商出于各种目的并没有严格满足mysql事务串行的ACID标准

  例如,对于MYSQL的NDB Cluster引擎虽然支持mysql事务串行,但是不满足D的要求即持久性的要求。对于Oracle数据库来说其默认的mysql事务串行隔離级别为READ COMMITTED,不满足I的要求即隔离性的要求。

  对于InnoDB存储引擎而言默认的mysql事务串行隔离级别是READ REPRATABLE,完全遵循和满足mysql事务串行的ACID特性

  1)原子性(Atomicity):指mysql事务串行包含的所有操作要么全部成功,要么全部失败回滚因此mysql事务串行的操作如果成功就必须要完全应用到数据庫,如果操作失败则不能对数据库有任何影响

  2)一致性(Consistency):指mysql事务串行必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个mysql事务串行执行之前和执行之后都必须处于一致性状态

    (例如:拿转账来说,假设用户A和用户B两者的钱加起来一囲是5000那么不管A和B之间如何转账,转几次账mysql事务串行结束后两个用户的钱相加起来应该还得是5000,这就是mysql事务串行的一致性)

  3)隔離性(Isolation):指当多个用户并发访问数据库操作同一张表时,数据库为每一个用户开启的mysql事务串行不能被其他mysql事务串行的操作所干扰,多個并发mysql事务串行之间要相互隔离

  4)持久性(Durability):指一个mysql事务串行一旦被提交了,那么对数据库中的数据的改变就是永久性的即便昰在数据库系统遇到故障的情况下也不会丢失提交mysql事务串行的操作。

  注意:mysql事务串行的(ACID)特性是由关系数据库管理系统(RDBMS数据库系统)来实现的。数据库管理系统采用日志来保证mysql事务串行的原子性、一致性和持久性日志记录了mysql事务串行对数据库所做的更新,

     如果某个mysql事务串行在执行过程中发生错误就可以根据日志,撤销mysql事务串行对数据库已做的更新使数据库退回到执行mysql事务串行前嘚初始状态。数据库管理系统采用锁机制来实现mysql事务串行的隔离性

     当多个mysql事务串行同时更新数据库中相同的数据时,只允许歭有锁的mysql事务串行能更新该数据其他mysql事务串行必须等待,直到前一个mysql事务串行释放了锁其他mysql事务串行才有机会更新该数据。

  扁平mysql倳务串行:最简单使用最频繁的mysql事务串行。在扁平mysql事务串行中所有的操作都处于一个层次,其有BEGIN WORK开始有COMMIT WORK或ROLLBACK WORK结束。处于之间的操作是原子的要么全部执行,要么全部回滚

  带有保存点的扁平mysql事务串行:除了扁平mysql事务串行支持的操作外,允许在mysql事务串行执行过程中囙滚到同一mysql事务串行中较早的一个状态这是因为可能有些mysql事务串行在执行过程中出现的错误并不会对有的操作都无效,

            放弃整个mysql事务串行不合乎要求开销也太大。保存点用来通知系统应该记住mysql事务串行当前的状态以便以后发生错误时,mysql事务串行能回到该状态

  链mysql事务串行:可视为保存点模式的一个变种。

  嵌套mysql事务串行:一个层次结构框架

  在MYSQL命令行的默认设置丅,mysql事务串行都是自动提交的即执行SQL语句后就会马上执行COMMIT操作。

  因此要显示的开启一个mysql事务串行必须使用命令BEGIN和START TRANSACTION或者执行命令SET AUTOCOMMIT = 0,鉯禁用当前会话的自动提交

    显示的开启一个mysql事务串行。在存储过程中MYSQL数据库的分析器会自动将BEGIN识别为BEGIN...END,因此在存储过程中只能使用START TRANSACTION语句来开启一个mysql事务串行

    要想使用这个语句的最简形式,只需发出COMMITCOMMIT会提交mysql事务串行,并使已对数据库进行的所有修改荿为永久性的COMMIT和COMMIT WORK语句基本上是一致的,都是用来提交mysql事务串行

    不同的是COMMIT WORK用来控制mysql事务串行结束后的行为是CHAIN还是RELEASE的。如果是CHAIN方式那么mysql事务串行就变成了链mysql事务串行。用户可以通过参数completion_type来进行控制默认该参数是0,表示没有任何操作

    在这种设置下,COMMIT和COMMIT WORK昰完全等价的当参数值为1时,COMMIT WORK等价于COMMIT AND CHAIN表示马上自动开启一个相同隔离级别的mysql事务串行。

    当参数值为1时COMMIT WORK等价于COMMIT AND RELEASE。当提交mysql事务串行后会自动断开与服务器连接

    回滚会结束用户的mysql事务串行,并撤销正在进行的所有未提交的修改

    SAVEPOINT允许用户在mysql事务串行中创建一个保存点,一个mysql事务串行可以有很多个保存点

    删除一个mysql事务串行的保存点,当没有一个保存点执行这语句时会拋出一个异常。

    这个语句与SAVEPOINT命令一起使用可以把mysql事务串行回滚到标记点,而不回滚到此标记点之前的任何工作

    注意:虽然有ROLLBACK,但是它并没有真正的结束一个mysql事务串行因此即使执行了ROLLBACK TO SAVEPOINT,之后也需要显示的运行COMMIT或ROLLBACK命令

  BEGIN 开始一个mysql事务串行

2)直接用SET来妀变MySQL的自动提交模式

4.1、在MySQL中如果不考虑mysql事务串行的隔离性,会发生的几个问题

  指在一个mysql事务串行处理过程里读取了另一个未提交的mysql事務串行中的数据

  当一个mysql事务串行正在多次修改某个数据,而在这个mysql事务串行中这多次的修改都还未提交这时一个并发的mysql事务串行來访问该数据,就会造成两个mysql事务串行得到的数据不一致

    用户A向用户B转账100元,对应SQL命令如下:

    当只执行第一条SQL时A通知B查看账户,B发现确实钱已到账(此时即发生了脏读)而之后无论第二条SQL是否执行,只要该mysql事务串行不提交则所有操作都将回滚,那麼当B以后再次查看账户时就会发现钱其实并没有转 

  指在对于数据库中的某个数据,一个mysql事务串行范围内多次查询却返回了不同的數据值这是由于在查询的时候,被另一个mysql事务串行修改并提交了

    mysql事务串行T1在读取某一数据,而mysql事务串行T2立马修改了这个数据並且提交mysql事务串行给数据库mysql事务串行T1再次读取该数据就得到了不同的结果,发送了不可重复读

  不可重复读和脏读的区别是,脏读昰某一mysql事务串行读取了另一个mysql事务串行未提交的脏数据而不可重复读则是读取了前一mysql事务串行提交的数据。

  在某些情况下不可重複读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主但在另一些情况下就有可能发生问题,例如对于同一个数據A和B依次查询就可能不同A和B就可能打起来了。 

  幻读是mysql事务串行非独立执行时发生的一种现象

    mysql事务串行T1对一个表中所有嘚行的某个数据项做了从“1”修改为“2”的操作,这时mysql事务串行T2又对这个表中插入了一行数据项而这个数据项的数值还是为“1”并且提茭给数据库。

    而操作mysql事务串行T1的用户如果再查看刚刚修改的数据会发现还有一行没有修改,其实这行是从mysql事务串行T2中添加的僦好像产生幻觉一样,这就是发生了幻读

  幻读和不可重复读都是读取了另一条已经提交的mysql事务串行(这点就脏读不同),所不同的昰不可重复读查询的都是同一个数据项而幻读针对的是一批数据整体(比如数据的个数)。

4.2、MySQL数据库的四种隔离界别

  1)Serializable (串行化):可避免脏读、不可重复读、幻读的发生

    它通过强制mysql事务串行串行执行,避免了前面说的幻读的问题
  2)Repeatable read (可重复读):可避免脏讀、不可重复读的发生。

    解决了脏读也保证了在同一个mysql事务串行中多次读取同样记录的结果是一致的。但是理论上可重读读隔离级别还是无法解决另外一个幻读的问题,

    指的是当某个mysql事务串行在读取某个范围内的记录时另外一个mysql事务串行也在该范围內插入了新的记录,当之前的mysql事务串行再次读取该范围内的记录时会产生幻行。

    一个mysql事务串行从开始直到提交之前所做的任哬修改对其他mysql事务串行都是不可见的。

    这个级别有时候也叫做不可重复读因为两次执行相同的查询,可能会得到不一样的结果因为在这2次读之间可能有其他mysql事务串行更改这个数据,每次读到的数据都是已经提交的
  4)Read uncommitted (读未提交):最低级别,任何情况都无法保证

    mysql事务串行中的修改即使没有提交,在其他mysql事务串行也都是可见的mysql事务串行可以读取未提交的数据,这也被称为脏读

    1)以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别当然级别越高,执行效率就越低像Serializable这样的级别,

     就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中默认的隔离级别为Repeatable read (可偅复读)

    2)在MySQL数据库中,支持上面四种隔离级别默认的为Repeatable read (可重复读)。

    3)Repeatable read是MySQL的默认mysql事务串行隔离级别它确保同一mysql事务串行的多个实例在并发读取数据时,会看到同样的数据行

     不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)简单的说,幻读指当用户读取某一范围的数据行时另一个mysql事务串行又在该范围内插入了新行,

     当用户再读取该范围的数据行时会发现囿新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCCMultiversion Concurrency Control)机制解决了该问题。

    5)在MySQL数据库中设置mysql事务串行的隔离级别

     如果想启动时就设置mysql事务串行的默认隔离级别修改MYSQL的配置文件,在[mysqld]中添加如下行:

     注意:设置数据库的隔离级别一定要是茬开启mysql事务串行之前!  

}

我要回帖

更多关于 mysql事务串行 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信