MySQL篇:事务
MySQL篇事务一、为什么要有事务数据库为了存储数据而生事务是为了实现ACIDACID原子性要么全做要么全部做–undo log一致性数据在事务前后满足所有规范–业务代码原子性、隔离性、持久性隔离性一个事务的执行不受其余事务影响–MVCC锁持久性提交的数据不可以丢失–redo log二、三个核心日志1.undolog逻辑日志作用保证事务原子性为MVCC提供支持1.把旧值写入undolog2.修改 Buffer Pool 里的数据页。3.记录回滚指针这行记录的回滚指针会找到undolog的旧值用于回滚如果需要回滚就沿着回滚指针找到旧值如果事务未提交那么undolog就不可以删除因为MVCC要通过它来查询历史版本的数据2.redolog物理日志每次直接修改磁盘太慢了所以会先写日志在异步刷盘1.修改在内存中的数据页2.写入redolog把那个表中的那个页偏移量多少写了什么记下来3.返回成功只要redolog写成功了就会回复客户端提交成功数据页在等空闲的时候在慢慢刷盘4.异步刷盘后台线程将脏页数据刷入磁盘3.binlog记录所有操作用于数据恢复与主从复制redolog与binlog逻辑必须一致否则主从数据会乱。流程1.prepare阶段redolog写入并刷盘状态为prepare2.写binlogbinlog日志写入3.commit阶段redolog状态改为commit崩溃时恢复:redolog是commit直接提交redolog是prepare但binlog不完整回滚redolog是prepare且binlog完整提交MVCC实现由回滚指针、undilog、readview1、readview决定可以看什么事务第一次执行查询是会生成一个readview然后会通过特定算法判断这个事务他可以看见的版本2、undolog通过回归指针找到历史版本在通过readview决定可以看到那个版本这样就比避免不可重复读的问题读当前读Select for update、update等会读取最新版本并且加锁防止篡改快照读普通的Select通过readview找到可见版本隔离级别与readviewRC隔离级别下每次查询都会生成新的readviewRR会使用事务一开始生成的Readview幻读MVCC解决的是快照读的幻读问题当前读是使用NEXT-Key Lock解决的他是行锁与间隙锁的组合即防止修改记录也防止修改记录的间隙大事务风险1.undolog膨胀大事务长时间不提交undolog不清理undolog可能被写满2.锁持有时间长由于行锁间隙锁一致不释放阻塞其余请求连接池打满3.大事务的binlog一次性写入从库导致从库瞬间延迟4.崩溃恢复慢未提交的大事务回滚时间长排查-- 查找运行超过 30 秒的事务 SELECT * FROM information_schema.INNODB_TRX WHERE trx_started DATE_SUB(NOW(), INTERVAL 30 SECOND)\G -- 找到对应的连接获取执行的 SQL SELECT * FROM information_schema.PROCESSLIST WHERE ID [thread_id]\G -- 紧急处理杀掉连接 KILL [thread_id];事务失效1.非public方法因为Spring AOP默认只代理public方法2.同类方法调用一个方法调用加入了transactional注解的方法不会走代理注解失效3.异常被捕获在方法内部加入了try-catchSpring接收不到异常信号4.非RuntimeException默认只会回滚RuntimeException 与Error 可以指定rollback出现异常就要回滚5.传播属性设置不当Propagation.REQUIRES_NEW会让外部事务挂起内部事务独立提交。如果内部事务回滚外部事务捕获了异常继续提交就会导致部分数据不一致。