数据库的隔离级别mysql_MySQL的隔离级别

一、读未提交(READ-UNCOMMITTED)

当事务隔离级别设置为READ-UNCOMMITTED(读未提交)时,在这种状态下,一个会话更新的数据会被其他的会话马上看到,即使该更新的数据尚未被事务所提交(commit)。

打开两个会话,分别设置它们的隔离级别。

会话一:

13861c4059ef3f44244ad5d7cf1dfa6a.png

由图可见,会话一的session隔离级别被设置为READ-UNCOMMITTED(读未提交)。

会话二:

e2fb66e169e4ca8933f427afe4d2427e.png

由图可见,会话二的session隔离级别被设置为REPEATABLE-READ(可重复读)。

我们将在表classes(存储引擎为InnoDB)下做测试,首先先来看下classes都已有哪些数据:

62d500682b0fcec6f57f59792285e76f.png

由图可见classes里面现在有3条数据。

在会话一中新增一条新数据但不提交:

2c13aa013854c6e7dd8e481a72762505.png

如图所示,在会话一中新增数据“Middle four”,虽未提交,但在会话一中马上就能查看到。

那在会话二中是否能看到?

63cf058e9d3c12f6a7f6df16caf9e9b9.png

由图可见,会话二无法看到在会话一中未提交的数据。为什么会出现这种情况?因为会话二中的session隔离级别为REPEATABLE-READ,无法脏读,即无法查看到未提交数据。那是否更改为READ-UNCOMMITTED就可以查看得到呢?

0a787941ef5c515d00e343bc846d1798.png

如图所示,当session隔离级别更改为READ-UNCOMMITTED时,会话二中即马上能看到会话一中未提交的数据。

如果此时会话一中执行回滚(rollback),那么会话一和会话二都会马上看到class_num=’10004’的数据已不存在。

会话一:

4ba6c622560c0c8985c64346235b1f47.png

会话二:

5849b1217edbfde1a033016db602f4c7.png

结论:当一个会话的(session)事务隔离级别被设置为READ-UNCOMMITTED时,那么它将可以马上看到其他会话更新的未提交数据,也既会出现脏读。

二、读已提交(READ-COMMITTED)

当事务隔离级别设置为READ-COMMITTED(读已提交)时,在这种状态下,一个会话更新的数据不会被其他的会话马上看到,除非该更新的数据已被事务所提交(commit)。

将会话一和会话二的session隔离级别都设置为READ-COMMITTED:

会话一:

2c9ab31c82143d7d2b46cd705216fcb0.png

会话二:

fd1f4e909a430e32a295d17268f787ea.png

然后在会话一开启一个新事务,并插入一条新数据,但先不要提交,如图:

0171d13854f6f182021b339228a6f98e.png

由图可知,此时会话一可以查到该未提交的数据,和前面session设置为READ-UNCOMMITTED一样,那是不是说明会话一出现了脏读?

看看会话二是否也可以查看得到:

7086fddc9c618b0a9ba39523ebdeaf25.png

由图可知,会话二无法读取到会话一中未提交的数据。那这就说明会话一中出现的情况(能读取自己未提交的数据)并不是脏读,因为会话二和会话一的隔离级别都是READ-COMMITTED,如果会话一出现了脏读,那么会话二也会出现。

那这是什么情况?本人认为这是因为它们是在同一个事务里,所以前面的操作对后面的操作是可见的,也即是后面的操作认为前面的操作已完成,所以它可以获取前面更新的数据。

此时会话一提交事务,会话二马上可以看到提交的事务:

78dcc031da1f602da3b465ae4681b138.png

总结:当一个会话的(session)事务隔离级别被设置为READ-COMMITTED时,那么它只可以看到其他会话已经提交的数据。

三、可重复读(REPEATABLE-READ)

当事务隔离级别设置为REPEATABLE-READ(可重复读)时,在这种状态下,同一个事务中的多次查询结果都是一致的(既不会出现不可重复读的现象),即使在此期间其他会话更新了数据,这些数据对其也是不可见的。

将会话一和会话二的session隔离级别都设置为REPEATABLE-READ:

会话一:

86141f0446c0dc7647c723fc0fd26e3b.png

会话二:

f10ed4d72da83d5036bb5e3e8193deb1.png

此时在会话一中开启事务,并查看现有数据,先不做commit:

b8c90387bb3ccf3fc240b4abdb83edb2.png

现在一共有5条数据。此时,我们通过会话二插入一条新数据:

c44dca014b93ef808ac170177c460db0.png

然后再回到会话一,重新查看数据:

dd6836e954303ac8731267ae242db0d6.png

由图可见,会话二更新的数据对其不可见。

会话一提交事务后再查看数据:

2f4d7957e13b79c96f3cf9e8a49bcc1a.png

此时会话二添加的数据已可查看。

由此可见,当事务的隔离级别被设置为REPEATABLE-READ后,同一个事务中的select语句查出的结果都是一致的,其他事务在此期间提交的数据将对其不可见。

四、串行化(Serializable)

当事务隔离级别设置为SERIALIZABLE(串行读)时,在这种状态下,一个会话事务中的select操作将会阻塞其他事务的写(add、update和delete)操作,但不会阻塞读。

将会话一和会话二的(session)事务隔离级别都设置为SERIALIZABLE:

会话一:

7183505fde3f6839de12764750df814a.png

会话二:

2045244efff73d44cfdb1c6c08d8b6b3.png

在会话一开启新事务,然后select下数据,但先不做commit操作:

62df06a43b7513250309401d172ec608.png

此时在会话二中插入一条新数据,发现无法插入,插入操作一直被阻塞:

5b945f41a20656124eea229b512908ba.png

但select操作未被阻塞:

c46b814b5dfec6d1c36efdeee3e82c0b.png

在会话一中执行commit操作,然后重新开启一个事务,并插入一条新数据,但先不提交:

1e8d9549eed270d62070f6690d47a0a3.png

此时在会话二中针对会话一新添的数据的任何写操作都会被阻塞:

a4b6911801d1966b012ee04cdf18b792.png

但其他数据的读写操作不会被阻塞:

20e020582827d179a1c7612b8b43468a.png

由此可以得出结论,当(session)事务的隔离级别被设置为SERIALIZABLE时,一个会话中的select操作会阻塞其他会话中的写操作,但不会阻塞select操作,而且一个会话中的写操作,会阻塞其他会话对同一条数据进行写操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值