MySQL数据库中的事务隔离与其他并发事务的讲解

在MySQL中,事务隔离级别定义了事务与其他并发事务互相看见对方改变的数据的情况。SQL标准规定了四种隔离级别,具体如下:

  • 序列化(SERIALIZABLE):事务串行执行,即每个事务必须等待上一个事务结束后才能开始执行。这确保了事务之间不会互相干扰,但是也导致了并发性能的降低。
  • 可重复读(REPEATABLE READ):在同一个事务内,多次读取同样数据时,结果都是一致的,无论其他事务是否已经修改过这些数据。但是,在事务提交之后,其他事务可以改变数据,这时本事务看到的是修改前的数据。
  • 提交读(READ COMMITTED):只能看见已经提交的其他事务所做的修改。换句话说,一个事务开始时,只能看见开始之前已经提交的所有事务所做的修改。本事务内所做的修改在其他事务提交之前是不可见的。
  • 未提交读(READ UNCOMMITTED):能看见其他事务做出的未提交的修改。这意味着本事务可能读取到脏数据,即尚未提交的数据。

 脏读(dirty read): 当一个事务读取另一个事务尚未提交的修改时,产生脏读;

不可重复读(nonrepeatable read): 同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生不可重复读;

幻读(phanton read): 同一查询在统一事务中多次进行,有无其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻读。

四种隔离级别
隔离级别脏读不可重复读幻读加锁读
Read uncommitted 读未提交不加锁
Read committed   读已提交×不加锁
Repeatable read  可重复读    ×××加锁
Serializable     可串行化×××加锁


#四种隔离别
-- Read uncommitted 读未提交 脏读 不可重复读 幻读 加锁读
-- Read committed   读已提交 	  不可重复读 幻读 不加锁
-- Repeatable read  可重复读			  不加锁
-- Serializable     可串行化			   加锁

-- 查看当前会话隔离级别
SELECT @@tx_isolation
-- 查看系统当前隔离级别
SELECT @@global.tx_isolation
-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 设置系统当前隔离级别
-- set session transaction isolation level [隔离级别名]

具体实例演示:

-- 演示MySQL的事务隔离级别
-- 1.开了两个控制台
-- 2.查看当前MySQL的隔离级别
SELECT @@tx_isolation;

# mysql> SELECT @@tx_isolation;
-- +-----------------+
-- | @@tx_isolation  |
-- +-----------------+
-- | REPEATABLE-READ |
-- +-----------------+

-- 3.把其中一个控制台的隔离级别设置成 Read uncommitted

注意事项:将两表同时开启事务 start trancaction;

如果在A未提交时,B控制台读到,A控制台未提交时的数据,证明脏读;

如果在A提交后,B控制台读到,A控制台修改删除的数据,证明不可重复读;

如果在A提交后,B控制台读到,A控制台插入的数据,证明幻读;

ps:正常情况下,B控制台应该读取的是,当时B控制台开启时的数据,并不是实时更新的数据!

1.证明 Read uncommitted 读未提交的脏读、不可重复读、幻读

041e89f3a10d42438995ed390c9b6f34.png3d477495936d4877b274df1761f4d408.png

3e9a6fef32434dbb8a0243935664a81a.pngca4679869fd44a9f9885f95b0b764a58.png

 

7017fb09f3e24bf8bd67965a86862aa6.png

这是另一个控制台,也可以同步查到数据 

e13266be94f24cadb8422952400f0e8c.png

c09631546ad34b19b099fd5ef9897903.pngfd3d89109d8644349be25b2d84627a73.png

 在A控制未提交时,以及提交后,B控制台都能查询到相关的数据改变,则证明以上;

2.证明 Read committed 不可重复读、幻读

把B控制台改为read committed;

a2cd22fc118a4c118d4443f4b12bad4a.png

d458ddb1c54e4351b4e4be66148977c5.png 0095a4ba31bc4ecab3c8ffedb56cbc38.png

 当A控制台再次插入数据且未提交时,B控制台查不到数据;脏读无;

710525e10383436ba1dcdc1b727d8af3.png1bfa6e43a1f14a608ef6402bcf6e8319.png

 当提交后B控制台查到数据,此时为不可重复读和幻读;

3.证明 Repeatable read 不存在 脏读、不可重复读、幻读

初始状态:

现在进行更改数据:

 

 当A控制台未提交时,B控制台查不到数据变化

 当A控制台提交后,B控制台依旧查不到数据变化,说明,脏读、不可重复度、幻读都不存在;

4.证明 Serializable 不存在 脏读、不可重复读、幻读,且是加锁的

 同时开启两个事务,将B控制台设置为serializable;

 在A控制台进行数据操作,输入数据以及更改数据,在B控制台进行查询时,光标一直在闪烁中。此处就体现了锁,因为A事务正在占用该表,B控制台不能对其进行查看以及相关操作。

 在B控制台进行了一会的等待后,出现了相关的语句,意思时,锁等待超时,尝试重启事务。

 在A控制台,提交事务后,B控制台才能对该表进行相关的操作。

 

 此处也可以证明了,Serializable,不存在脏读、不可重复度、幻读,且是加锁。

小结:

  1. 正常情况下,当时开启一个事务时,两个事务不可以相互访问。因为,此时事务还未提交,操作者,可能对数据进行修改,如果B事务访问正在修改的A事务,读到临时数据,此时为脏读
  2. 当A、B事务同时开启时,A事务修改,删除 提交后,B事务依旧不能访问A事务对该表进行的操作。因为,正常情况下,A、B事务相互独立,不应该收到对方的影响。此时,为不可重复度
  3. 当A、B事务同时开启时,A事务插入操作 提交后,B事务依旧不能访问A事务对该表进行的操作。因为,正常情况下,A、B事务相互独立,不应该收到对方的影响。此时,为幻读