十一、MySQL 事务底层与高可用原理
一、事务基础知识(针对插入、修改)
MySQL中只有innodb支持事务
1、显式事务
手动开关
begin / begin work / start tracsaction;rollback;commit;
2、隐式事务
自动开关,自动提交
show variables like 'autocommit';
3、MySQL事务实现的机制
WAL(write ahead logging):预写式事务,写数据之前记录日志。
4、redo log
重做日志
- 保证事务的持久性
- 写数据操作之前,相关操作写入redo log
- 防止MySQL宕机,可以实现数据恢复
5、undo log
回滚日志
- 保证事务的原子性
二、redo日志
提交操作,是一个物理日志,不是逻辑日志。
1、作用
服务器不挂的时候,redo log没用,还会拉低性能,只有MySQL挂了的时候才有用。
- 为了保证事务的持久性,在执行事务时,会先将操作计入redo log。
- 如果事务提交过程中宕机,就从redo log恢复。
- 如果没宕机,那就抹去redo log的日志;
2、redo log的存储位置
show variables like 'datadir';
3、redo log日志文件
名称:ib_logfile0;ib_logfile1;
4、redo log的目录
show variables like 'innodb_log_group_home_dir';
5、redo log的大小 - 48MB
show variables like 'innodb_log_file_size';
6、redo log的数量
默认 = 2个,最大 = 100个。
show variables like 'innodb_log_files_in_group';
7、redo log有两个的原因
轮流上岗,防止写满了没地方写。
8、保存日志
使用保存数据页的方式(16KB)
- 低效
- 一个数据页里面可能只修改了一个字段。
使用保存SQL语句的解释的方式
- 系统表空间 100号页 -- 偏移量1000处(字节的数据,原有值 = 1) 修改为2。
9、redo log的一般格式
- 操作类型 53种
- 表空间id
- 页编号
- 具体数据
- 占用空间小
10、最简单的redo log
一个表没有主键和唯一性索引,会自动维护一个隐藏字段row_id
- 在内存中维护一个【全局变量】,记录row_id 当前自增到几了;
- 当这个【全局变量】的值为256的倍数,会把变量的值刷新到【系统表空间,页号=7的页中】的(Max row_id)属性;对这个页的修改就会以redo log日志保存起来(type = MLOG_8BYTE);
- MLOG_8BYTE:表示在页面某个偏移量写入一个8字节的日志;
- offset :偏移量;
11、复杂的redo log类型
12、redo log 刷入磁盘
事务在commit之后,要将操作结果刷到磁盘,同时抹去redo log;
-- 默认=1,即时刷入
show variables like 'innodb_flush_log_at_trx_commit';
13、崩溃后恢复为什么不用binlog?
binlog 没法定位恢复到哪里。
三、undo日志
1、概念
- 负责回滚操作。
- 针对事务的原子性。
- 以版本链为基础实现。
2、detele 对应的undo log
delete不会直接将记录加入垃圾链表,而是设置为一个【中间状态 detele_mask = 1,但是未加入垃圾链表】,commit之后才加入垃圾链表;
目的是实现事务的隔离级别;比如读已提交,如果直接加入垃圾链表,那么就读不到这个还没提交的删除记录;
被删除的记录会放入垃圾链表(page_free)的尾部;
删除的版本链 格式:
- 【被删除记录】的回滚指针指向【被删除记录】的旧的回滚指针
- 新的回滚指针指向旧的回滚指针,旧的回滚指针指向旧的undo日志,实现回滚
3、update 对应的undo log
两种情况:不更新主键、更新主键
不更新主键 | 更新主键 |
就地更新 | 1、将旧记录进行delete mark操作 2、创建一条新记录 |
先删除旧记录,再插入新记录 | |
1条 undo log TRX_UNDO_UPD_EXIST_REC | 2条 undo log TRX_UNDO_DEL_MARK_REC TRX_UNDO_INSERT_REC |