定义
保证一组操作要么全部成功,要么全部失败。
引擎层实现
ACID特性
ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)
- 原子性:最小操作单位
- 一致性:事务操作前后,数据总量不变
- 隔离性:多个事务间,相互独立
- 持久性:提交、回滚后,持久化保存
隔离性 & 隔离级别
- 读未提交(read uncommitted):
读到了其他事务未提交的数据,即脏读(dirty read) - 读已提交(read committed):
其他事务提交前、提交后,当前事务两次查询到的数据不一致,即不可重复读(non-repeatable read) - 可重复读(repeatable read):
保证一个事务执行过程中看到数据前后一致。但假如其他事务有insert、delete、update操作,改变了数据量,当前事务将无法通过select获得这些改变结果,即幻读(phantom read)。
另外的解释:某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。 - 串行化(serializable)
将记录加锁,锁冲突时必须等待当前操作事务的提交或回滚后,才能操作。
解决一切问题
修改隔离界别:
-- 可选参数有:
-- READ-UNCOMMITTED,
-- READ-COMMITTED,
-- REPEATABLE-READ,
-- SERIALIZABLE
transaction-isolation = xxx
事务隔离的实现
各个read-view通过回滚日志,读取到一个数值的不同版本,这是通过MVCC多版本并发控制实现的。
一个回滚日志,将在系统里没有比此日志更早的read-view的时候被删除。
建议:尽量避免使用长事务。
- 占用大量存储空间:
长事务中存在许多老旧的任务视图,这个长事务提交前,它可能用到的回滚记录都必须保留,导致占用大量存储空间。 - 占用锁资源
-- 查询持续时间超过60s的长事务
select * from information_schema.innodb_trx
where TIME_TO_SEC(timediff(now(),trx_started))>60
回滚日志
事务启动方式
-- 1、显示启动事务-----------------------------
begin transaction
## 或
start transaction
# 具体操作
commit
## 或
rollback
-- 2、关闭当前线程自动提交--------------------
set autocommit=0
# 具体操作
# 任何query语句都将启动事务,且必须手动提交或回滚
# 可能导致意外的长事务
commit
## 或
rollback
建议:使用显示启动事务的方式
如何避免长事务对业务的影响
应用开发端:
- 打开自动提交:set autocommit=1
- 确认是否有不必要的只读业务,可以去掉。
- set max_execution_time,控制每个语句的最长执行时间。
数据库端:
- 监控information_schema.innodb_trx表,设置长事务阈值,超过就报警、KILL
- 业务功能测试阶段,输出所有general_log,分析日志行为,提前发现
- 5.6 or higher,把innodb_undo_tablespaces设置成2