#yyds干货盘点#MySQL学习-为啥有时候事务的隔离没有生效

Posted 汤圆学Java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#yyds干货盘点#MySQL学习-为啥有时候事务的隔离没有生效相关的知识,希望对你有一定的参考价值。

前言

我们知道mysql的事务可以实现语句之间的隔离(ACID中的I),使得各个操作之间互不干扰;

但是有时候我们会发现事务并没有起到隔离的作用;

下面我们就来解释下事务隔离失效的原因以及相关的玩具场景;

目录

  1. 事务的启动时机
  2. 事务隔离失效的例子
  3. 解决办法

正文

1. 事务的启动时机

我们前文了解了事务的启动方式分为显式启动(begin)和隐式启动;

而我们一般采用的启动方式就是显式启动,即通过begin来启动事务;

但是这里的begin并不会马上启动事务,它只是表示事务的创建时机,真正启动事务是在后续的第一条SQL语句执行时;

这就是为啥有时候明明开启了事务,但是没有起到隔离作用的原因;

当然如果是隐式启动事务,那么就不会存在这个问题;

因为隐式启动就是一条SQL语句执行时自动开启一个事务,然后语句执行完成后自动提交事务,这样在语句执行期间 就不会存在间隙,其他语句也就无法影响到这个语句的执行;

但是隐式启动只能实现隔离性,无法保证操作期间数据的一致性,所以一般不推荐隐式启动;

2. 事务隔离失效的例子

例子的思路就是:

  • 开启两个事务
  • 然后在第一个事务begin之后,执行第一条SQL语句之前,启动第二个事务,并修改一条数据;
  • 再回到事务A去查询这条数据
  • 如果查询到的是修改后的数据,则说明事务A没有起到隔离的作用;

下面我们开启两个mysql窗口,并在窗口1中开启一个事务A: begin;

这时事务A并没有启动,begin只是用来创建事务;

接下来我们在窗口2中开启事务B(begin),修改一条数据(之前的name=1,现在改为jalon),提交事务

这时我们再回到窗口1,去事务A中查询id=1这条数据,会发现查到的是最新的name=jalon

这是因为事务A的begin开启事务后并没有马上启动事务,而是在下面的select * from test where id=1;语句执行时,才真正启动事务;

这时会创建一个视图,用来确保事务A执行期间数据的一致性;

而这个时候,事务B已经修改了id=1的数据,并提交了事务;

所以此时创建的视图会包含最新的数据,即事务B修改过的数据;

3. 解决办法

其实事务的启动有一个快捷方法:start transaction with consistent snapshot

这个命令的意思就是:创建+启动事务,相当于begin命令以及begin到第一条SQL语句执行之间的间隙

这时我们再重复上面的例子,不过不是以begin的形式开启事务,而是快捷命令start transaction with consistent snapshot:

下面的窗口1先创建并启动事务A,然后窗口2创建事务B,修改数据,提交事务B;

然后再回到窗口1查询数据;

可以看到,查询的数据还是旧的数据(新数据为name=ling);

这说明事务A的隔离生效了,这就是start transaction with consistent snapshot的功劳;

总结

  • 事务隔离失效的原因:
    • 因为事务的begin只是创建事务,而真正启动事务是在第一条SQL语句执行时;
    • 如果在begin和执行第一条SQL语句期间,其他事务修改了数据,那么事务A就会读到最新的数据,而不是begin时的数据;
  • 事务隔离失效的解决:
    • 使用创建并启动事务的快捷命令,start transaction with consistent snapshot
    • 如果隔离级别是读提交RC,那么该命令就无效了,因为只要一个事务提交了更新,其他事务都会读到最新的数据,而不是事务启动时的数据
  • 事务视图的创建时机:
    • 如果是begin命令,则是在第一条SQL语句执行时创建一致性视图
    • 如果快捷启动命令start transaction with consistent snapshot,则该命令执行时就会创建一致性视图

以上是关于#yyds干货盘点#MySQL学习-为啥有时候事务的隔离没有生效的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL事务超全知识总结#yyds干货盘点#

#yyds干货盘点# MySQL RC事务隔离级别的实现

#yyds干货盘点# MySQL - 存储引擎

#yyds干货盘点#MySQL学习-索引的基础篇(下)

#yyds干货盘点#几种数据库存储引擎比较

#yyds干货盘点# InnoDB解决幻读的方案--LBCC&MVCC