mysql事务与隔离级别

本文深入探讨事务的概念,包括其原子性、一致性、隔离性和持久性。详细解释了事务的默认属性,常见并发异常及其解决方案。同时,对比分析了不同隔离级别的实现方式,如基于锁和基于锁+MVCC,以及它们如何解决并发问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是事务?

1、事务是一组sql语句,事务中的所有sql语句被当做一个操作单元,要么全部执行成功,要么全部执行失败,事务内的sql语句被当做一个整体,被当做一个原子进行操作。

 

事务的特性?

1、原子性,整个事务中的所有操作要么全部执行成功,要么全部执行失败后回滚到最初状态。

2、一致性,数据库总是从一个一致性状态转为另一个一致性状态。一致性状态包含数据库完整性约束,系统的状态反应数据库本应描述的现实世界的真实状态。

3、隔离性,并发执行的事务相互之间不会影响。

4、持久性,事务一旦提交,事务所做的修改将会永久保存。

 

事务默认属性

1、默认自动提交on,即每执行一条sql语句就会把这条sql当做一个单语句事务进行提交,在事务中执行时自动提交失效,提交由commit执行决定

2、默认隔离级别repeatable-read(可重复读)

 

数据库常见的并发异常

1、脏写(第一类丢失更新),是指事务回滚了其他事务对数据项的已提交修改

2、丢失更新(第二类丢失更新),指事务覆盖了其他事务对数据的已提交修改,导致这些修改好像丢失了一样

3、脏读,是指一个事务读取了另一个事务未提交的数据

4、不可重复读,是指一个事务对同一数据的读取结果前后不一致(脏读和不可重复读的区别在于:前者读取的是事务未提交的脏数据,后者读取的是事务已经提交的数据,只不过因为数据被其他事务修改过导致前后两次读取的结果不一样,由其他事务的数据修改引起)

5、幻读,是指事务读取某个范围的数据时,因为其他事务的操作导致前后两次读取的结果不一致(幻读和不可重复读的区别在于,不可重复读是针对确定的某一行数据而言,而幻读是针对不确定的多行数据。因而幻读通常出现在带有查询条件的范围查询中,由其他事务的数据插入或者删除引起)

 

事务的隔离级别(基于锁实现)

RUC(读未提交)

读不加锁,写加排他锁,并到事务结束之后释放。(因此不存在数据库中的丢失更新问题)

RC(读已提交):不可重复读,幻读

事务对当前被读取的数据加行级共享锁(当读到时才加锁),一旦读完该行,立即释放该行级共享锁;事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加行级排他锁,直到事务结束才释放。(读取时加共享锁(注意读取完锁就会被释放,不会到等事务结束),因此避免了脏读问题,但读完后其他事务还是可以修改数据,因此不能解决不可重复读的问题)

RR(可重复读):幻读

事务在读取某数据的瞬间(就是开始读取的瞬间),必须先对其加 行级共享锁,直到事务结束才释放;事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加 行级排他锁,直到事务结束才释放。

序列化

事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放;

事务在更新数据时,必须先对其加 表级排他锁 ,直到事务结束才释放。

 

事务的隔离级别(基于锁+MVCC)

MVCC的引入主要是解决了读加锁的问题,即读写冲突的问题。

RC(读已提交):不可重复读,幻读

RC级别中,基于MVCC实现,读默认不需要加锁,解决了脏读问题,但由于每一次读都会生成新的ReadView,因此无法解决不可重复问题和幻读问题。

RR(可重复读):

RR级别中,基于MVCC实现,读默认不需要加锁,解决了脏读,不可重复读,以及部分幻读问题,事务只生成一次ReadView,因此在同一事务过程是可重复读的,并且部分场景没有幻读。

注意:MVCC只应用在RC和RR两种隔离级别中,因此这里只看RC和RR两种隔离级别

 

注意:丢失更新问题,我这里把它分为业务中的丢失更新问题和数据库中的丢失更新

业务中的丢失更新问题,一般是如下场景:

事务A,读取了1记录,余额为100,

事务B,读取了1记录,余额为100,

事务A,执行一系列逻辑操作后,将1记录的余额更新为90,update a set balance=90 where id=1

事务A提交事务

事务B,执行一系列逻辑操作后,将1记录的余额更新为110,update a set balance=110 where id=1

事务B提交事务

若要解决类似场景的问题,必须在读取1记录的时候通过排他锁的方式,即select * for update,这样直到A事务执行完毕,B事务才能读取1记录继续执行。

数据库中的丢失更新问题,一般是如下场景:

事务A,update a set balance=100 where id=1

事务B,update b set money=100 where id=1

若update操作没有排他锁,则事务B的修改会导致事务A的修改丢失,但在RC和RR两种隔离级别中,update等当前读都是有锁的,因此RC和RR不存在数据库中的丢失更新问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值