12)REPEATABLE-READ隔离级别 马克-to-win:既 然我们教材用mysql,我们仔细研究一下mysql缺省情况,即两个窗口都是REPEATABLE-READ(可重复读)级别的情况。 mysql的策略是,只要你叠加在别人的修改之上修改了, 在你提交之前,是可以看到这种修改的,即使你的窗口级别是REPEATABLE-READ(可重复读)。
前言MySQL默认的隔离级别是REPEATABLE-READ(可重复读)。虽然它可以提供一定程度上的数据一致性和隔离性,但并不能完全解决幻读问题。 在REPEATABLE-READ隔离级别下,只能保证在同一事务中相同的查询语句返回相同的结果,但无法防止其他事务插入新的数据,从而导致当前事务的查询结果发生变化。 幻读演示MySQL默认隔离级别REPEATABLE-READ(可重复读)会话一会话二MySQL [test]> select * from t1;+------+| id |+------+| version();+-----------+| version() |+-----------+| 8.0.21 |+-----------+1 row in set (0.000 sec)总结在REPEATABLE-READ FOR UPDATE语句进行的读取操作)在REPEATABLE-READ隔离级别下仍然可能遇到幻读。
隔离级别 脏读 不可重复读 幻影读 READ-UNCOMMITTED √ √ √ READ-COMMITTED × √ √ REPEATABLE-READ × × √ SERIALIZABLE × × × MySQL 的默认隔离级别 MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。 | +-----------------+ 注意: InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别下,使用的是 Next-Key Lock 锁算法,因此可以避免幻读的产生 可以说,InnoDB 存储引擎默认支持的隔离级别 REPEATABLE-READ(可重读) ,已经可以完全保证事务的隔离性要求,即达到了 SQL 标准的 SERIALIZABLE(可串行化) 隔离级别。 隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内容):,但 InnoDB 存储引擎默认使用的 REPEATABLE-READ(可重读)并不会有任何性能损失
快照读和当前读混用造成的异常,不能算是幻读 网络上有一些文章说 MySQL repeatable-read 是会出现幻读的,复现用例如下: 当前读的效果就是要读取最新版本,实际上是把隔离级别从 repeatable-read 如果这个说服不了你,那我也举个简单的例子: 我们是不是得说这个例子说明了 repeatable-read 允许“P2不可重复读异常现象”?显然不能。 对于不可重复读,repeatable-read 隔离级别是明确不允许的。这就说明了当前读和快照读混用带来的异常不能称为幻读。 问题5:MySQL的 repeatable-read 隔离级别允许宽松解释的幻读吗? 所以对于 MySQL 这样基于 MVCC 实现的 RR 隔离级别,大家就当不会出现幻读,而且是符合“repeatable-read” 语义的。
Variable_name | Value | +-----------------------+-----------------+| transaction_isolation | REPEATABLE-READ ----------------------+-----------------+1 row in set (0.00 sec)mysql> SET transaction_isolation = 'REPEATABLE-READ ';Query OK, 0 rows affected (0.00 sec) 永久:将以下两个参数添加至配置文件 my.cnf,并重启 MySQL: transaction_isolation = 'REPEATABLE-READ --------------------+-----------------+1 row in set (0.00 sec) mysql> SET transaction_isolation = 'REPEATABLE-READ ; Query OK, 0 rows affected (0.00 sec) 永久:将以下两个参数添加至配置文件 my.cnf,并重启 MySQL: transaction_isolation = 'REPEATABLE-READ
REPEATABLE-READ:可重复读 将隔离级别置为REPEATABLE-READ # 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLEREAD 可重复读,SERIALIZABLE串⾏ transaction-isolation=REPEATABLE-READ 重启mysql: C:\Windows\system32>net stop mysql 幻读演示 幻读只会在REPEATABLE-READ(可重复读)级别下出现,需要先把隔离级别改为可重复 读。 将隔离级别置为REPEATABLE-READ # 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLEREAD可重复读,SERIALIZABLE 串⾏ transaction-isolation=REPEATABLE-READ 重启mysql: C:\Windows\system32>net stop mysql mysql 服务正在停⽌.. mysql
REPEATABLE-READ(可重复读) : 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。 ---- 隔离级别 脏读 不可重复读 幻读 READ-UNCOMMITTED √ √ √ READ-COMMITTED × √ √ REPEATABLE-READ × × √ SERIALIZABLE × × × MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。 | +-----------------+ 从上面对 SQL 标准定义了四个隔离级别的介绍可以看出,标准的 SQL 隔离级别定义里,REPEATABLE-READ(可重复读)是不可以防止幻读的。 InnoDB 实现的 REPEATABLE-READ 隔离级别其实是可以解决幻读问题发生的,主要有下面两种情况: 快照读 :由 MVCC 机制来保证不出现幻读。
问题分析 隔离级别问题 看到这样的情况,我们理所当然的猜测,应该是隔离级别不同导致的,环境A的隔离级别应该是REPEATABLE-READ,可重复读,什么是REPEATABLE-READ? 环境A和环境B都是REPEATABLE-READ,啊啊啊,那到底是为什么呢? 环境B: 我们现在来分析情况环境B,环境B是RedHat7,autocommit设置为1,表示事务自动提交开启,隔离级别是REPEATABLE-READ。 在auto_commit=on,隔离级别是REPEATABLE-READ,session1能看到session2在T2时刻提交的数据。 在auto_commit=off,隔离级别是REPEATABLE-READ,session1不能看到session2在T2时刻提交的数据。
注:MySQL 的默认隔离级别为repeatable-read级别 并且在MySQL中 repeatable-read级别还可以处理幻读,这是 MySQL独有的 next-keylock 实现的。 MVCC 只在read-committed和repeatable-read 两个隔离级别下工作,其他两个隔离级别: read-uncommitted,总是读取最新的数据行,而不会读当前事务版本的数据行。 前面我们说过:MVCC 只在 read-committed 和 repeatable-read两个隔离级别下工作,而 read-committed 和 repeatable-read 的区别就在于它们生成 repeatable-read —— 在第一次查询数据时生成一个 ReadView,之后的读都复用之前的。 ReadView,而repeatable-read 只在第一次进行普通 select 操作前生成一个 ReadView,之后的查询操作都重复使用这个 ReadView 就好了。
global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ 7.2 设置事务的隔离级别 7.2.1 第一种方式:修改my.ini配置文件 可选值: - READ-UNCOMMITTED - READ-COMMITTED - REPEATABLE-READ `tx1`(`id`, `c1`, `c2`) VALUES (1, ' REPEATABLE-READ', ' REPEATABLE-READ'); Query OK, 1 row affected + | id | c1 | c2 | +----+------------------+------------------+ | 1 | REPEATABLE-READ | REPEATABLE-READ | +----+------------------+------------------+ 1 row in set (0.00 sec) 7.3.4 第四级别
REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。 ---- 隔离级别 脏读 不可重复读 幻读 READ-UNCOMMITTED √ √ √ READ-COMMITTED × √ √ REPEATABLE-READ × × √ SERIALIZABLE MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。 | +-----------------+ MySQL InnoDB 的 REPEATABLE-READ(可重读)并不保证避免幻读,需要应用使用加锁读来保证。 因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 READ-COMMITTED(读取提交内容) ,但是你要知道的是 InnoDB 存储引擎默认使用 REPEATABLE-READ(
注: MySQL默认隔离级别为 REPEATABLE-READ,innodb_rollback_on_timeout为OFF,本文基于innodb表(支持事务)进行测试。 1. 测试过程 2.1 隔离级别REPEATABLE-READ & innodb_rollback_on_timeout =OFF a) 测试过程: session A session B mysql> begin 2.3 隔离级别REPEATABLE-READ & innodb_rollback_on_timeout =ON 注:innodb_rollback_on_timeout不能在线修改,需要修改配置文件后重启生效 隔离级别 innodb_rollback_on_timeout 结果 REPEATABLE-READ OFF 超时回滚前的SQL不会自动回滚 READ-COMMITTED OFF 超时回滚前的SQL不会自动回滚 表观察事务情况,在不同的版本中事务情况不一样.例如,隔离级别REPEATABLE-READ & innodb_rollback_on_timeout=on的情况下,MySQL5.6 中整个事务回滚后会自动创建一个事务
--------+ | VARIABLE_NAME | VARIABLE_VALUE | +---------------+-----------------+ | tx_isolation | REPEATABLE-READ OFF | +---------------+-----------------+ 2 rows in set (0.01 sec) List-2中可以看出事物隔离级别是repeatable-read
而mysql的缺省隔离级别是REPEATABLE-READ。在mysql中,我打开两个 窗口,分别代表两个事务,这两个窗口的缺省的隔离级别就是REPEATABLE-READ。 而窗口2因为没变,级别还是REPEATABLE-READ。 更多请看:https://blog.csdn.net/qq_44594371/article/details/103188820
| REPEATABLE-READ | +-----------------------+------------------------+ 1 row in set, 2 | REPEATABLE-READ | +-----------------------+------------------------+ 1 row in set, 2 | REPEATABLE-READ | +-----------------------+------------------------+ 1 row in set, 2 | REPEATABLE-READ | +-----------------------+------------------------+ 1 row in set, 2 | REPEATABLE-READ | +-----------------------+------------------------+ 1 row in set, 2
REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。 image.png MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。 | +-----------------+ 这里需要注意的是:与 SQL 标准不同的地方在于InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别下使用的是Next-Key 所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的SERIALIZABLE(可串行化)隔离级别。 因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内容):,但是你要知道的是InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读
这时候B提交事务 客户端B commit; 客户端A select * from test_tx; 读到了已提交的变更,这就是不可重复度 可重复读 客户端A set tx_isolation=' repeatable-read '; start transaction; 客户端B set tx_isolation=' repeatable-read '; start transaction; 客户端A select commit; 客户端A select * from test_tx; A没有将B提交的数据查出来,解决了不可重复读的问题,难道说就没有问题了么 验证幻读 客户端A set tx_isolation=' repeatable-read '; start transaction; 客户端B set tx_isolation=' repeatable-read '; start transaction; 客户端A select
隔离级别分为4种: 读未提交:READ-UNCOMMITTED 读已提交:READ-COMMITTED 可重复读:REPEATABLE-READ 串行:SERIALIZABLE 上面4中隔离级别越来越强 REPEATABLE-READ:可重复读 将隔离级别置为REPEATABLE-READ # 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ 幻读演示 幻读只会在REPEATABLE-READ(可重复读)级别下出现,需要先把隔离级别改为可重复读。 将隔离级别置为REPEATABLE-READ # 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE 串行 transaction-isolation=REPEATABLE-READ 重启mysql: C:\Windows\system32>net stop mysql mysql 服务正在停止..
mysql》一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ , SERIALIZABLE. 2 [mysqld] 3 transaction-isolation = REPEATABLE-READ 这里全局默认是REPEATABLE-READ,其实MySQL本来默认也是这个级别 REPEATABLE-READ(可重读) 1)A设置事务隔离级别,进入事务后查询一次 2)B开始事务,并对user表进行修改 3)A查看user表数据,数据未发生改变 4)B提交事务 5)A再进行一次查询 结果已经更新 7)A重新开始事务,并对user表进行修改 8)B表重新开始事务,并对user表进行修改,修改被挂起,直到超时,对另一条记录修改却成功,说明A对表进行修改时加了行共享锁(可以select) REPEATABLE-READ
REPEATABLE-READ(可重复读) :对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。 不过, SERIALIZABLE 之外的其他隔离级别可能也需要用到锁机制,就比如 REPEATABLE-READ 在当前读情况下需要使用加锁读来保证不会出现幻读。 MySQL 的默认隔离级别是什么? MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。 | +-----------------+ 从上面对 SQL 标准定义了四个隔离级别的介绍可以看出,标准的 SQL 隔离级别定义里,REPEATABLE-READ(可重复读)是不可以防止幻读的。 InnoDB 实现的 REPEATABLE-READ 隔离级别其实是可以解决幻读问题发生的,主要有下面两种情况: 快照读 :由 MVCC 机制来保证不出现幻读。