事务-详解

事务执行流程可参考:https://www.cnblogs.com/gaokeji/p/16375323.html
ACID
扁平事务
带保存点扁平事务 innodb支持
savepoint name; rollback to savepoint name; release savepoint name;
回滚到一个早期状态,但事务没结束,别忘了commit or rollback
链事务 innodb支持,考虑到保存点易失,要是能持久化部分就好了,将提交事务和开始另一事务原子化
嵌套事务 叶子节点负责实际操作, 高层节点负责逻辑控制,子事务提交需父事务提交后才生效,父事务回滚导致其所有子事务回滚, innodb不支持,可用savepoint模拟
分布式事务 innodb支持(基于xa,隔离级别必须Serialiable ,此级别每个select语句 自动加lock in share mode, )
RM/TM/AP(应用程序,向各RM发具体操作),两阶段提交
语法:XA START name/END name/PREPARE name/RECOVER/COMMIT name
我们多用编程语言进行分布式事务如jta
还有一种内部xa事务,如binlog和innodb 之间,详情见下文group commit

事务tips:
一般默认自动提交(但最好不要这样,容易出错) 存储过程中用start transaction,不能用begin(冲突)
在存储过程中控制事务,我们很难知道事务是否成功,若失败,原因是什么,因此存储过程只封装逻辑
应该在程序中控制事务(根据错误显式控制commit or rollback)
commit work 行为取决于completion_type, rollback work 一样
0默认值,等同于commit
1,等同于commit and chain,开启链事务
2,等同于commit and release, 提交后断开连接
有很多语句隐式提交(自动提交),DDL(包括truncate table,所以通过它删除表不可回滚
事务统计 session/global status (com_commit com_rollback com_rollback_to_savepoint,当然这3个都不包 括隐式提交和回滚),可用来统计TPS
不要循环中提交(500次成功,501次失败那怎么办,前面的已经无法回滚了,还有多次commit的性能问题,应该在事务中循环)
长事务(很长时间):若中途硬件坏了,rollback的代价太大了,很不灵活,应分隔成小事务

undo 提供回滚和MVCC,行日志
逻辑日志(逆操作,页可能就不一样了),一般在事务提交后且**没有其他事务引用后(MVCC)**回收,本身也会产生redo log(需持久化保护),一般来说undo log放于共享表空间
rollback segment 含1024个 undo log segment ,每个事务占用一个undo log segment(在内进行undo page申请),限制了同时在线事务为1024,1.1版本允许多个rollback segment(128个,128*1024)
undo log segment与undo page 关系:segment 可含多个页,page也可含多个segment,看单个事务(segment)产生的undo日志大小,segment内有单个事务的多条undo log record,segment
undo 页重用: 考虑一下,segment占了3.5或0.5page,有0.5page空闲,事务提交时,因为剩余空间大于1/4,这page可重用, 下一个事务的segment分配可从这0.5page开始

insert undo log 事务提交后回收(没有其他事务能看见,自然无法引用,可无purge操作),记录单表的多条主键
update undo log (update和delete时生成),等purge删除
delete: 标记删除,purge线程完成最终删除
update:非主键列直接更新,主键列删除+新增(两条undo log)

purge thread(purge):1 清除undo log 2 清除deleted-flag记录
delete和对主键更新(delete+insert): 标记记录头的deleted-flag,生成undo log,事务提交后,purge线程判断不再有引用,真正删除记录和undo log。
history list (按事务提交顺序链接,每个事务node指向自己的undo log segment)
purge thread 如何purge:先trx1的undo,trx1同page还有其他事务(trx3)的undo,清除trx3的undo,同page依然有trx5的undo(但是trx5被其他事务引用MVCC不能清除),回到history list,找到trx2,继续如上操作,这样可避免大量随机读取(尽力顺序读)

group commit:innodb 事务提交时write/fsync redo log, 同时多个事务提交,多次fsync,性能问题,考虑一次fsync服务于多个事务。
如何实现:1 写入commit(也是一个redo entry),时间短 2 write and fsync,时间长
有一个事务开启了write/fsync过程,中途不断有新事务向redo log buffer写入commit entry,没关系,这次刷盘会把所有的全部刷入磁盘。

开启了binlog后的问题:
为保证 binlog 和存储引擎事务 一致性,两阶段事务,内部xa/分布式事务
1 innodb prepare
2 写binlog (sync_binlog)
3 innodb 写入redo log (1 写commit entry 2 write and fsync)
不能写了binlog没写redo(宕机),重启后检查并在innodb层提交
假设T1,T2两事务,T1先2,T2再2,T2再3,T1再3,是否可以呢? 不可以,若宕机通过在线备份恢复的话,检测到T2已完成(2,3步骤),会认为先开始的T1也完成了,实际T1的redo log没写。
因此必须获取prepare_commit_mutex 这把锁来完成内部三个步骤,各事务串行提交,自然没有group commit

5.6的解决方案(blgc/binary log group commit)
优势:binlog 和redo log 都是group commit,且移除了prepare_commit_mutex
Leader 事务(队列中第一个) ,follower 事务
flush: binlog 写入操作系统缓存
sync: binlog同步,一次fsync
commit: 按顺序调用innodb层commit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值