mysql四种事务隔离级别详解图,mysql四种事务隔离级别详解表

mysql四种事务隔离级别详解图,mysql四种事务隔离级别详解表,MySQL四种事务隔离级别详解

本文主要详细介绍MySQL的四个事务隔离级别的相关信息。本文中的示例代码非常详细,具有一定的参考价值。感兴趣的朋友可以参考一下。

本文的测试环境:Windows 10 cmd MySQL5.6.36 InnoDB

一、事务的基本要素(ACID)

1.原子性:事务开始后,所有操作要么完成,要么根本不做,不可能中途停滞。如果事务执行中出现错误,将回滚到事务开始前的状态,所有操作将如同没有发生一样。也就是说,商业是一个不可分割的整体,就像化学中的原子一样,是构成物质的基本单位。

2.一致性:在事务开始之前和之后,数据库的完整性约束不会被破坏。比如A给B转账,A不可能扣款,B却不收。

3.隔离:同时只允许一个事务请求相同的数据,不同事务之间不存在干扰。举个例子,A正在从一张银行卡上取钱,B在A的取钱流程结束之前,无法向这张卡转账。

4.持久性:事务完成后,事务对数据库的所有更新都将保存到数据库中,并且不能回滚。

总结:原子性是事务隔离的基础,隔离和持久化是手段,最终目的是保持数据一致。

二、事务的并发问题

1.脏读:事务a读事务b更新的数据,然后b回滚,所以事务a读的数据是脏数据。

2.不可重复读取:事务A多次读取同一数据,而事务B在事务A的多次读取过程中更新并提交数据,导致事务A多次读取同一数据时结果不一致。

3.魔读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE成绩,但系统管理员B此时插入了具体分数的记录。当系统管理员A完成修改后,发现还有一条记录没有被修改,好像产生了幻觉。这就是所谓的魔法阅读。

总结:不可重复读数和幻像读数很容易混淆。不可重复读数侧重于修改,而幻像读数侧重于添加或删除。解决不可重复读取的问题只需要锁定满足条件的行,解决幻影读取的问题需要锁定表。

四、用例子说明各个隔离级别的情况

1.未提交的读取:

(1)打开客户端a,设置当前交易模式为读取未提交,查询表账户初始值:

(2)在客户端A的交易提交之前,打开另一个客户端B并更新表帐户:

(3)此时,虽然客户端B的交易尚未提交,但是客户端A可以查询客户端B的更新数据:

(4)一旦客户端B的事务因为某种原因回滚,所有操作都会被取消,客户端A查询的数据实际上是脏数据:

(5)在客户端A上执行update语句update account set balance=balance-50,其中id=1,李雷的余额是400而不是350。你没有问数据的一致性是不是很奇怪?如果你这么想,那就太天真了。在应用程序中,我们将使用400-50=350,我们不知道其他会话回滚。为了解决这个问题,

2.阅读已提交。

(1)打开客户端a,设置当前交易模式为读提交,查询表账户初始值:

(2)在客户端A的交易提交之前,打开另一个客户端B并更新表帐户:

(3)此时客户端B的交易还没有提交,客户端A无法查询B的更新数据,从而解决了脏读问题:

(4)客户b的交易提交

(5)客户端A执行与上一步相同的查询,结果与上一步不一致,即不重复问题。在应用程序中,假设我们在客户端A的会话中,李雷的余额是450,但是其他事务将李雷的余额值更改为400。我们不知道如果用450的值做其他运算会不会有问题,但是这个概率真的很小。

3、可以反复阅读

(1)打开客户端a,设置当前交易模式为可重复读取,查询表账户初始值:

(2)在客户端A的交易提交之前,打开另一个客户端B,更新表账户并提交。客户端B的事务实际上可以修改客户端A的事务查询的行,即mysql的可重复读取不会锁定事务查询的行。这出乎我的意料。当sql标准中的事务隔离级别是可重复读取时,读写操作必须锁定行,但mysql没有锁。我去了那里。注意锁定应用程序中的行,否则会将步骤(1)中李雷的余额作为400作为中间值来进行其他操作。

(3)在客户端A执行步骤(1)的查询:

(4)执行步骤(1),李雷余额仍为400,与步骤(1)的查询结果一致,不存在不重复的问题;然后更新balance=balance-50其中ID=1,balance不会变成400-50=350。李雷的余额值在步骤(2)中用350计算,所以是300,但是数据的一致性没有被破坏。这个有点神奇,可能是mysql的特点吧。

mysql select * from account

- - -

| id |姓名|余额|

- - -

| 1 |李雷| 400 |

| 2 |韩梅| 16000 |人

| 3 |露西| 2400 |

- - -

集合中的行(0.00秒)

mysql更新账套balance=balance - 50其中id=1;

查询正常,1行受影响(0.00秒)

匹配的行数:1已更改:1警告数:0

mysql select * from account

- - -

| id |姓名|余额|

- - -

1 |李雷| 300 |

| 2 |韩梅| 16000 |人

| 3 |露西| 2400 |

- - -

集合中的行(0.00秒)

(5)在客户端A启动交易,查询表账户的初始值。

mysql启动事务;

查询正常,0行受影响(0.00秒)

mysql select * from account

- - -

| id |姓名|余额|

- - -

1 |李雷| 300 |

| 2 |韩梅| 16000 |人

| 3 |露西| 2400 |

- - -

集合中的行(0.00秒)

(6)在客户端B启动交易,添加一条新数据,其中余额字段的值为600,并提交。

mysql启动事务;

查询正常,0行受影响(0.00秒)

mysql插入帐户值(4, lily ,600);

查询正常,1行受影响(0.00秒)

mysql提交;

查询正常,0行受影响(0.01秒)

(7)计算客户端A中余额的总和,值为300 16000 2400=18700。如果不包括客户端B的值,那么计算客户端A提交后的余额之和,实际上变成了19300。这是因为包含了客户端B的600。站在客户的角度,客户看不到客户端B,会觉得大饼丢了人间,还有600多个。但是,在应用程序中,我们的代码可能会向用户提交18700。如果一定要避免这种小概率的发生,应该采用下面要介绍的事务隔离级别“序列化”。

MySQL select sum(balance)from account;

-

总和(余额)

-

| 18700 |

-

集合中的1行(0.00秒)

mysql提交;

查询正常,0行受影响(0.00秒)

MySQL select sum(balance)from account;

-

总和(余额)

-

| 19300 |

-

集合中的1行(0.00秒)

4.序列化

(1)打开客户端A,设置当前交易模式为可序列化,查询表账户初始值:

mysql设置可序列化的会话事务隔离级别;

查询正常,0行受影响(0.00秒)

mysql启动事务;

查询正常,0行受影响(0.00秒)

mysql select * from account

- - -

| id |姓名|余额|

- - -

1 |李雷| 10000 |

| 2 |韩梅| 10000 |人

| 3 |露西| 10000 |

| 4 |百合| 10000 |

- - -

集合中的行(0.00秒)

(2)打开a客户端B,设置当前事务模式为可序列化,插入一条记录并报错,表被锁定。插入失败。当mysql中的事务隔离级别为serializable时,表将被锁定,因此不会有神奇的读取。这种隔离级别在并发性上是极低的,往往一个事务占用一个表,而其他几千个事务只能干瞪眼。开发中很少用到。

mysql设置可序列化的会话事务隔离级别;

查询正常,0行受影响(0.00秒)

mysql启动事务;

查询正常,0行受影响(0.00秒)

mysql插入帐户值(5, tom ,0);

错误1205 (HY000):超过锁定等待超时;尝试重新启动交易

补充:

1.根据SQL规范中规定的标准,不同数据库的具体实现可能会有一些差异。

2.mysql中默认的事务隔离级别是可重复的,读取的行不会被锁定。

3.当事务隔离级别为序列化时,读取数据将锁定整个表。

4.看这篇文章的时候,站在开发者的角度,你可能会觉得不能反复读,读的很神奇。逻辑上没有问题,最后的数据还是一致的。但是从用户的角度来看,他们只能看到一个事务(只能看到客户端A,不知道客户端B的卧底存在),没有考虑事务并发执行的现象。一旦相同的数据被多次读取而得到不同的结果,或者凭空出现新的记录,它们可能会生成。

5.在mysql中执行一个事务时,最终结果不会存在数据一致性的问题,因为在一个事务中,mysql在执行一个操作时可能不会使用前一个操作的中间结果,但会根据其他并发事务的实际情况进行处理。看似不合逻辑,却保证了数据的一致性;但是,当在应用程序中执行事务时,一个操作的结果将被下一个操作使用,并进行其他计算。这是我们必须小心的。重复读取时要锁行,序列化时要锁表,否则会破坏数据的一致性。

6.在mysql中执行一个事务时,mysql会根据每个事务的实际情况综合处理,使得数据一致性不被破坏。但是在应用一个应用的时候不像mysql那样按照逻辑套路出牌,不可避免的会出现数据一致性问题。

7.隔离级别越高,数据完整性和一致性越好,但对并发性能的影响也越大。你不能鱼与熊掌兼得。对于大多数应用来说,可以将数据库系统的隔离级别设置为先提交读,这样可以避免脏读,具有良好的并发性能。虽然会导致不可重复读取、幻影读取等一些并发问题,但应用可以在个别场合采用悲观锁或乐观锁来控制这些问题。

这就是本文的全部内容。希望对大家的学习有帮助,支持我们。

mysql四种事务隔离级别详解图,mysql四种事务隔离级别详解表