首页 > 数据库 >mysql事务隔离级别和spring事务传播机制

mysql事务隔离级别和spring事务传播机制

时间:2024-09-19 16:18:10浏览次数:10  
标签:事务 name 幻读 spring mysql 执行 方法 id

一、事务并发会出现的三个问题

数据库事务具有ACID4个特性:

A:Atomic,原子性,将所有SQL作为原子工作单元执行,要么全部执行,要么全部不执行;

C:Consistent,一致性,事务完成后,所有数据的状态都是一致的,即A账户只要减去了100,B账户则必定加上了100;

I:Isolation,隔离性,如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离;

D:Duration,持久性,即事务完成后,对数据库数据的修改被持久化存储。

对于两个并发执行的事务,如果涉及到操作同一条记录的时候,可能会发生问题。因为并发操作会带来数据的不一致性,包括脏读、不可重复读、幻读等。数据库系统提供了隔离级别来让我们有针对性地选择事务的隔离级别,避免数据不一致的问题。

1、Dirty reads--读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。

ORDER 事务A 事务B
1 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
2 BEGIN; BEGIN;
3 UPDATE table SET name="B" where id=1;
4 SELECT * FROM table WHERE id = 1;(读到name=B)
5 ROLLBACK;
6 SELECT * FROM table WHERE id = 1;(读到name=A)
7 COMMIT;
2、non-repeatable reads--数据不可重复读。比如事务B中两处读取数据name的值。在第一读的时候,name是A,然后事务A就把name的数据改成B,事务B再读一次,结果就发现,name竟然就变成B了,造成事务B数据混乱。
ORDER 事务A 事务B
1 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
2 BEGIN; BEGIN;
3 SELECT * FROM table WHERE id = 1;(读到name=A)
4 UPDATE table SET name="B" where id=1;
5 COMMIT;
6 SELECT * FROM table WHERE id = 1;(读到name=B)
7 COMMIT;
3、phantom reads--幻象读数据

可以看到,session A 里执行了三次查询,分别是 Q1、Q2 和 Q3。它们的 SQL 语句相同,都是 select * from t where d=5 for update。这个语句的意思你应该很清楚了,查所有 d=5 的行,而且使用的是当前读,并且加上写锁。现在,我们来看一下这三条 SQL 语句,分别会返回什么结果。

  1. Q1 只返回 id=5 这一行;

  2. 在 T2 时刻,session B 把 id=0 这一行的 d 值改成了 5,因此 T3 时刻 Q2 查出来的是 id=0 和 id=5 这两行;

  3. 在 T4 时刻,session C 又插入一行(1,1,5),因此 T5 时刻 Q3 查出来的是 id=0、id=1 和 id=5 的这三行。

其中,Q3 读到 id=1 这一行的现象,被称为“幻读”。也就是说,幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。

这里,我需要对“幻读”做一个说明:

  1. 在可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入的数据的。因此,幻读在“当前读”下才会出现。什么是当前读?除了快照读其他都是当前读。而当前读的规则,就是要能读到所有已经提交的记录的最新值。所以才会出现幻读的情况,查到新插入的记录

  2. 上面 session B 的修改结果,被 session A 之后的 select 语句用“当前读”看到,不能称为幻读。幻读仅专指“新插入的行”。

针对MySQL InnoDB引擎的可重复读隔离级别,有两种方式避免幻读:

  1. 快照读(普通select语句),是通过MVCC 方式解决了幻读
  2. 当前读(select … for update),是通过next-key lock(记录锁+间隙锁)来解决幻读

二、四种隔离级别能解决的三个问题

1、Serializable:避免了一个事务中由于其他事务的插入操作造成的多次读取数据不一致的问题,避免了幻读,最严格的级别,事务串行执行,资源消耗最大;

2、REPEATABLE READ:保证了一个事务多次查询不会读取到已经由另一个事务提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。 也解决了部分幻读的情况。

3、READ COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。

4、Read Uncommitted:保证了读取过程中不会读取到非法数据。隔离级别在于处理多事务的并发问题。

三、PROPAGATION(spring事务传播机制)

  • PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。也就是说业务方法需要在一个事务中运行,如果
    业务方法被调用时,调用业务方法的行为(方法)已经处在一个事务中,那么就加入到该事务,否则为自己创建一个新的事务。
    (默认传播机制)

  • PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。也就是说如果业务方法在某个事务范围内被调用,
    则该方法成为该事务的一部分。如果业务方法在事务范围外被调用,则该方法在没有事务的环境下执行。

  • PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。也就是说业务方法只能在一个已经存在的事务中执行,
    业务方法不能发起自己的事务。如果业务方法在没有事务的环境下被调用,容器就会抛出例外。

  • PROPAGATION_REQUIRESNEW:新建事务,如果当前存在事务,把当前事务挂起。也就是说业务方法被调用时,不管是否已经存在事务,
    业务方法总会为自己发起一个新的事务。如果调用业务方法的行为(方法)已经运行在一个事务中,则原有事务会被挂起,新的事务
    会被创建,直到业务方法执行结束,新事务才算结束,原先的事务才会恢复执行。

  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,就把当前事务挂起。也就是说业务方法不需要事务。如果
    方法没有被关联到一个事务中,容器不会为它开启事务。如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,
    原先的事务便会恢复执行。

  • PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。也就是说业务方法绝对不能在事务范围内执行。如果业务
    方法在某个事务中执行,容器会抛出例外,只有业务方法没有关联到任何事务,才能正常执行。

  • PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。 如果没有活动事务, 则按REQUIRED属性执行。
    它使用了一个单独的事务, 这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对
    DataSourceTransactionManager事务管理器起效。

另外有一篇文章写的传播机制写的不错,附上链接>>>点击链接

标签:事务,name,幻读,spring,mysql,执行,方法,id
From: https://www.cnblogs.com/leecoder5/p/18420820

相关文章

  • mysql性能优化(索引)
    mysql大部分性能的问题都出在索引上,因此索引优化是头等大事1.最左匹配原则这是索引基本的匹配原则,这里不多说,只要记住索引是要按顺序创建的,mysql是按顺序去b+树上查找的就行2.Usingtemporary;Usingfilesort往往出现这个都代表着不好的情况,通常是在groupby和orderby的情况下......
  • 线上锁超时排查(手动事务transactionTemplate导致的诡异锁超时)---此篇篇幅很长,带好瓜子
    事情起因起因是某天线上突然不停报锁超时,重启后又会变正常,但是在某个时刻又会重复发生。这个是报错的日志(日志对检测这种bug不一定有用,唯一的作用就是告诉我们啥表被锁了,但是看不出因为啥被锁的)###SQL:INSERTINTOt_check_record(id,create_time,update_time,creator,opera......
  • 全网最简单ubuntu18.04+mysql5.7+nginx+uwsgi一次性部署Django!!!!!
    ubuntu18.04,自带python3.6,mysql5.7 Nginx*******************************1.安装nginx apt-getupdate apt-getupgrade apt-getinstallnginx 2.修改端口为81(可选),是一个链接 /etc/nginx/sites-enabled/default3.servicenginxreload4.servicenginx......
  • MySQL强化篇指优化思路总结
    基础--连接退出数据库连接:mysql-h地址-P接口-u用户名-p密码退出:exit或者/q数据库操作关键字create创建数据库createdatabase数据库名如:createdatabasetestdefaultcharsetutf8关键字show查看当前有哪些数据库showdatabase;查看创建数据库的语句......
  • Spring Cloud Gateway CORS 方案
    问题在SpringCloud项目中,前后端分离目前很常见,在调试时,会遇到两种情况的跨域:前端页面通过不同域名或IP访问微服务的后台,例如前端人员会在本地起HttpServer直连后台开发本地起的服务,此时,如果不加任何配置,前端页面的请求会被浏览器跨域限制拦截,所以,业务服务常常会添加如下代码设置......
  • mybatis 通过工厂模式将mapper接口的代理对象注入spring容器中
    MapperFactoryBean是MyBatis框架中用于创建Mapper对象的一个工厂类。getObject方法是该工厂类中的一个关键方法,用于返回实际的Mapper对象。具体来说,MapperFactoryBean通过getObject方法来创建和初始化Mapper接口的实现,从而可以在Spring容器中注入和使用这些Mappe......
  • 第十一章 【后端】商品分类管理微服务(11.4)——spring-boot-devtools
    11.4spring-boot-devtools官网:https://docs.spring.io/spring-boot/reference/using/devtools.htmlSpringBootDevTools是SpringBoot提供的一组易于使用的工具,旨在加速开发和测试过程。它通过提供一系列实用的功能,如自动重启、实时属性更新、依赖项的热替换等,极大地......
  • springboot+vue音乐网站【开题+程序+论文】
    系统程序文件列表开题报告内容研究背景随着互联网的飞速发展,音乐已成为人们日常生活中不可或缺的一部分。传统音乐获取方式如购买CD、磁带等逐渐淡出市场,取而代之的是更为便捷、多样的在线音乐服务。当前市场上虽已存在众多音乐网站,但它们在用户体验、歌曲分类的精细化、歌......
  • springboot+vue音乐网站【开题+程序+论文】
    系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,数字音乐已成为人们日常生活中不可或缺的一部分。音乐网站作为数字音乐传播的重要平台,不仅为用户提供了便捷的音乐获取渠道,还通过丰富的功能和个性化的服务,极大地丰富了人们的音乐体验。然而,当前市场上的音乐......
  • springboot+vue音乐网站【开题+程序+论文】
    系统程序文件列表开题报告内容研究背景随着互联网的飞速发展,数字化娱乐已成为现代人生活中不可或缺的一部分,其中音乐作为跨越文化和国界的艺术形式,更是受到了广大网民的热烈追捧。传统的音乐获取方式如购买实体唱片或通过电视广播已难以满足用户对音乐资源多元化、即时化、......