- 事务的四个特性
- 事务会产生的问题
- 脏读、不可重复读、幻读如何去解决
- 四个特性通过什么去保证呢
其中隔离性通过MySQL的锁和MVCC保证,
锁可以保证 写写事务,但是锁就意为着阻塞。
MVCC保证读读事务,还是读写事务,MVCC可以保证读写同步,通过MVCC可以实现提交读和可重复读两种隔离级别。
而原子性、一致性和持久性通过redo和undo来保证。
事务的四个特性
原子性:事务中的语句要么全部执行,要么全部不执行。
一致性:只一种一致性状态,例如100块钱怎么转都是100块,不会变多也不会变少
隔离性:事务之间互不影响
持久性:事务的影响是持久的。
事务会产生的问题
脏读:事务A读取了事务B回滚的事务。
不可重复读:事务A两次读取的数据不同。
幻读:事务A第二次读取的数据增多或减少。
幻读可以通过序列化或者MVCC解决,但是MVCC不完全保证不会出现幻读,如下情况:
事务A | 事务B
select ...
insert ...
update新增的那条数据
select ...
隔离级别
隔离级别 | 可能产生问题 | 原理 |
---|---|---|
未提交读 | 脏读、不可重复读、幻读 | |
提交读 | 不可重复读、幻读 | MVCC |
可重复读 | 幻读 | MVCC |
序列化 | 锁 |
Redo日志
为什么要有redo日志
我们都知道,为了更快的从mysql中读数据,mysql大叔为mysql设置了buffer pool这个一个缓冲在内存中,这个buffer pool有两个好处
- 它放在内存中读的快
- 改buffer pool中的缓冲页就行了,利用率高,由buffer pool统一来把数据存到磁盘中。
我们来讲讲buffer pool不足的地方: buffer pool中的缓冲页刷到磁盘中是随机IO,不是顺序IO,比较慢。为了保证持久性,mysql数据不丢失,mysql大叔创造了redo log,它顺序IO比较快,空间占用少。
redo日志的组成
- redo log buffer
- redo log file
redo log buffer
也是采用页的存储方式。log file和buffer的内容大致相同,都是指明哪个表空间,哪个数据页,哪个行修改了什么数据,是物理日志。
redo log block为512字节,redo log buffer16M
redo log file有两个,可复写,通过checkpoint保证
redo log的写入流程
事务执行
写入redo log buffer
写入buffer pool
事务提交
同步到redo log file
事务结束
redo log buffer的写入方式
0:每秒由子线程提交给操作系统同步
1:commit后由主线程同步(默认)
2:commit后交给操作系统的缓冲区,由操作系统同步
1的效率最低但是最安全,鱼和熊掌不可兼得。2只要操作系统不宕机还是可以同步的。
Undo日志
undo可以保证事务的原子性,及失败的事务可以回滚,不会有部分提交的情况。
undo可以分为insert undo和update undo,为啥这么分呢?insert的内容提交以后,insert undo就没啥用了,可以直接删除。而update undo的版本链需要给MVCC支持,所以不能直接删除,所以只是打了个delete_mark,之后由purge线程统一操作。
undo日志是逻辑日志,记录的是数据库变化内容。
MVCC