Mysql-行列转换
Mysql-事务复习
四大特性:原子性,一致性,持久性,隔离性。
事务实现
单个事务如何保证事务特性?关键点:1.事务回滚,2.事务结束提交。
事务回滚通过undo log保证,undo log 记录了事务修改前的日志数据。
事务提交通过redo log file保证,事务 commit后,数据会持久化到redo log file(磁盘)中。 redo log file 快满时,持久化undo log中的数据,清空redo log file。
具体的执行情况:

redo log file: 是顺序循环存储的日志文件,不像undo log是存储有关联关系的数据。redo log file 达到75%时,异步持久化undo log,redo log file达到90%时,使用同步操作持久化undo log。
单个事务
mysql中用undo log 和redo log file解决持久性问题。
事务进行一半系统崩溃,重启后如何保证事务的特性?
事务并发
多个事务之间产生什么样的影响?
不同的隔离级别下影响不同。
隔离级别
| 事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交(read-uncommitted)RU | 是 | 是 | 是 |
| 不可重复读(read-committed)RC | 否 | 是 | 是 |
| 可重复读(repeatable-read)RR | 否 | 否 | 否 |
| 串行化(serializable) | 否 | 否 | 否 |
mysql-mvcc
解决了什么:
mysql中RR隔离级别实现了,单事务内重复读一条数据,结果不变。
mysql中RC隔离级实现了,单事务内不会读取其他事务未提交的数据。
SQL实例
RR隔离级SQL实例
1 | # session1 |
如何保证可重复读:开始事务时拷贝readview。
RC隔离级SQL实例
1 | # 设置当前会话隔离级别为 读已提交 |
RU 隔离级SQL实例
1 |
|
原理实现
三个关键点:undo log,ReadView,版本号。
事务流程(涉及undo log 和版本号):每个事务以系统版本号为事务id,修改记录行时将事务id记录到隐藏列trx_id.隐藏列roll_pointer指向未修改的记录行。事务开始时copy read_view。
read_view记录当前进行中的事务id, 事务id大的可以看到事务id小的记录。
undo log
聚簇索引记录中了隐藏列trx_id、roll_pointer
版本号
readview
- 结构:
判断可见性
- 行记录事务id > readview 最大事务id 不可见,通过回滚指针找上一个记录
- 行记录事务id < readview 最小事务id 可见
- 行记录事务id = readview 事务数组中id 不可见
- 行记录事务id > readview 最小事务id < readview 最大事务id != 事务数组中的id 可见
readview建立时机:
- RR 事务开始时建立。第二次执行select不会重新拷贝readview,事务B提交事务后,事务B的事务id仍存在于事务A的readview中。事务A不会读取到事务B提交的数据。
- RC在事务中的每一条SQL语句执行时建立。其他事务未提交时,事务id存在于readview的事务数组中,不可见。
幻读
什么是幻读?因为事务B在事务A多次查询中间插入了数据,事务A读取结果不一致。
RR隔离级是否解决了幻读? 解决了。
如何解决的?MVCC+next key
RR下的幻读:
事务A update 全表后,查询到事务B insert的数据。
1 | #session1 |
1 | id username birthday sex address |
1 | #session2 |
1 | id username birthday sex address |
问题
RR为什么单事务读取数据一致?事务开始时拷贝readview。不再更新readview。
RC为什么出现重复读一条数据结果不一致?每一条语句执行时,拷贝readview。
RU为什么不会读取其他事务未提交的数据?其他事务id存在于readview中。select语句执行时 拷贝readview看到了其他事务的id。
RC可处理并发量大于RR?RR增加了间隙锁。