事务隔离
# 事务隔离
# 1.隔离级别
读未提交:当前事务能够读取到其它事务提交之前的所有变更。没有视图的概念。
读已提交:当前事务能够读取到其它事务提交之后的所有变更。每次执行sql语句都会重新创建一次视图,刷新快照。
可重复读:一个事务执行过程中,能够看到的数据和该事务启动时的数据状态保持一致。当前这份数据不受其它事务的影响。视图会在启动时就创建好了,启动时会创建一个全局快照。
串行化:对于数据库表中同一行记录,“写”之前会加上“写锁”,“读”之前会加上“读锁”,读写锁冲突时,必须等待前一个事务执行完毕释放锁之后才能进行。
# 2.事务隔离实现
长事务:运行时间比较长,长时间未提交(执行了很多语句忘记commit)的事务称为长事务。不使用长事务的原因①只要当前长事务未提交,那么与它相关的所有回滚记录都会保留,占据大量存储空间。②长期占用锁资源。
数据库多版本并发控制MVCC:查询一条记录时,同一条记录会存在多个不同的版本,每个版本数据对应一个事务id。
回滚日志:记录每个值被修改过的所有状态值。当系统判定没有事务(视图)用到这些回滚日志时,就会删除对应的回滚日志。就会如下图所示:

# 3.事务启动方式
启动事务一般有两种方式:
- 显示开启事务:begin transaction
- 设置set autocommit=0,每次自动事务,将线程的自动提交关闭。这个事务启动后会一直存在,持续到你显式调用commit才会断开事务连接。
建议使用commit work and chain语法,提交事务后自动启动下一个事务。
# 4.如何避免长事务
- 检查set autocommit是否被设置为0,如果设置为0那么所有SQL语句执行完毕之后,不会自动提交事务。因此需要把它改成1。
- 只读事务select不需要放到事务中执行。
- 根据业务本身估计,通过set max_execution 设置每个SQL语句执行的最长时间,避免单个语句执行过长时间。
- 从数据库端来看:①监控innoDB数据表,设置长事务阈值,超过报警。②设置回滚日志的表空间个数innodb_undo_tablespaces。
编辑 (opens new window)
上次更新: 2023/12/15, 15:49:57