zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

mysql系列-事务

mysql事务 系列
2023-06-13 09:15:04 时间

在mysql中,常见的存储引擎有innodb、myisam,memory等。其中innodb支持事务(transaction),而myisam,memory等不支持事务。

show engines;

一 事务的四大特征

1.1 原子性(Atomicity)

事务是一个不可分割的最小工作单位,事务中的操作只有成功及失败两种情况。

1.1.1 实现原理

事务的原子性是通过 undo log 来实现。

1.2 一致性(Consistency)

在事务开始之前和事务结束以后,数据库的完整性没有被破坏。

1.2.1 实现原理

通过原子性,持久性,隔离性来实现

1.3 隔离性(Isolation)

数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

1.3.1 实现原理

事务的隔离性是通过 (读写锁+MVCC)来实现的。

1.4 持久性(Durability)

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

1.4.1 实现原理

事务的持久性性是通过 redo log 来实现。

1.4.2 redo log组成

1、内存中重做日志缓冲 (redo log buffer),易丢失,存在内存。 2、重做日志文件 (redo log file),是持久的,保存在磁盘中

1.4.3 记录流程

1、先修改数据,后写日志。 2、redo日志比数据页先写回磁盘。 3、聚集索引、二级索引、undo页面的修改,均需要记录Redo日志。

二 事务的分类

事务分为隐式事务和显式事务。

2.1 隐式事务

DML语句(insert、update、delete)就是隐式事务。 该事务没有明显的开启和结束标记,它们都具有自动提交事务的功能。

2.2 显式事务

该事务具有明显的开启和结束标记; 禁用自动提交功能就是设置autocommit变量值为0【禁用】

2.3 开启事务的步骤

1、查看当前autocommit状态
    SELECT @@autocommit;
2、更新自动提交状态
    -- 关闭自动提交
    SET autocommit = 0;    
    -- 开启自动提交
    SET autocommit = 1;
3、开启事务
-- 开始一个事务BEGIN;
或者start transaction;
4、提交事务
-- 提交一个事务COMMIT;
5、回滚事务
-- 回滚一个事务ROLLBACK;

三 mysql事务隔离级别

3.1 默认事务隔离级别

SELECT @@tx_isolation;

默认隔离级别为:REPEATABLE-READ【可重复读】

3.2 读未提交

3.2.1 定义

允许事务读取未被其他事务提交的变更。(脏读、不可重复读和幻读的问题都会出现)

3.2.2 问题

1、脏读:读取到了还未提交的数据。解决:事务隔离级别调整为读已提交。

3.3 读已提交

3.3.1 定义

允许读取其他事务已提交的数据。

3.3.2 问题

1、不可重复读:该隔离级别内,前后读取的数据,可能不一致。

3.4 可重复读

3.4.1 定义

在同一个事务内,前后读取的同一条数据,内容一致。

3.4.2 问题

1、幻读:一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。【快照读主要无法解决新增数据的问题】

3.5 串行化

最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰。该级别可以防止脏读、不可重复读以及幻读

3.5.1 问题

数据库并发量低,性能差。

四 长事务

4.1 定义

运行时间比较长,长时间未提交的事务就可以称为长事务。

4.2 产生的原因

1、操作的数据比较多
2、大量的锁竞争
3、有其他非DB的耗时操作
4、事务粒度过大

4.3 产生的影响

1、降低db的并发承受量
2、锁定太多的数据,造成大量的阻塞和锁超时【slow log】
3、回滚所需要的时间比较长

4.4 解决方案

1、避免一次处理太多数据
2、避免不必要的查询
3、避免耗时太多的操作
4、降低事务的粒度

五 spring事务失效场景

5.1 事务方法访问修饰符非public

注意:Spring的声明式事务是基于动态代理实现的,如果事务是static、final的,同样无法通过动态代理,事务也是不会生效的。

5.2 抛出非spring事务支持的异常

5.3 数据库存储引擎不支持事务

如果使用MySQL且存储引擎是MyISAM,则事务是不起作用的,原因是MyIASM不支持事务。

5.4 事务所在类不被spring管理

加上@Service注解或者使用其他能注册成Spring Bean的方式或注解,使用spring容器管理,事务才能生效。

5.5 手动捕捉异常

手动捕捉异常,事务不会回滚。

5.6 传播类型不支持事务

Propagation.NOT_SUPPORTED:不在Transaction中运行,事务无效。

5.7 多线程调用

不在一个线程时,获取的数据库连接可能不是同一个,处于不同事务中,此时事务无效。 需要手动创建事务,控制事务提交及回滚。

思考

分布式事务的实现。