mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)

读取未提交 - 脏读问题

MySQL 事务隔离其实是依靠锁来实现的,加锁自然会带来性能的损失。而读未提交隔离级别是不加锁的,所以它的性能是最好的,没有加锁、解锁带来的性能开销。但有利就有弊,这基本上就相当于裸奔啊,所以它连脏读的问题都没办法解决。任何事务对数据的修改都会第一时间暴露给其他事务,即使事务还没有提交。

设置隔离级别方法可参考:https://blog.csdn.net/qq_39408664/article/details/119004699
在事务隔离级别基本操作下有介绍怎么去设置隔离级别。

下面来做个简单实验验证一下,首先设置全局隔离级别为读未提交。
mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第1张图片
设置完成后,只对之后新起的 session 才起作用,对已经启动 session 无效。如果用 shell 客户端那就要重新连接 MySQL ,如果用 Navicat 那就要创建新的查询窗口。

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

事务A 事务B
在这里插入图片描述 在这里插入图片描述
mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第2张图片 mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第3张图片
mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第4张图片
mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第5张图片
在这里插入图片描述 在这里插入图片描述

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



读取已提交-不可重复读问题

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

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

我们来做一下验证,首先把事务隔离级别改为读提交级别:
mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第6张图片
设置完成后,需要重新打开 session 窗口,也就是新的 shell 窗口才可以。

同样开启事务A和事务B两个事务,在事务A中使用 update 语句将 id = 1 的记录行 age 字段改为30。此时,在事务B中使用 select 语句进行查询,我们发现在事务A提交之前,事务B中查询到的记录 age 一直是14,直到事务A提交,此时在事务B中查询,发现 age 的值已经是 30 了。这就出现了一个问题,在同一事务中(本例中的事务B),事务的不同时刻同样的查询条件,查询出来的记录内容是不一样的,事务A的提交影响了事务B的查询结果,这就是不可重复读,也就是读取已提交隔离级别。

事务A 事务B
在这里插入图片描述 在这里插入图片描述
mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第7张图片 mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第8张图片
在这里插入图片描述 mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第9张图片
在这里插入图片描述
mysql 读取未提交(脏读问题)与读取已提交(不可重复读问题)_第10张图片
在这里插入图片描述

每个 select 语句都有自己的一份快照,而不是一个事务一份,所以在不同的时刻,查询出来的数据可能是不一致的。读提交解决了脏读问题,但是无法做到可重复读,也没办法解决幻读。



可重复读-幻读问题与串行化说明,参考:https://blog.csdn.net/qq_39408664/article/details/119037440

你可能感兴趣的:(MySQL,mysql,数据库)