MySql事务与锁机制原理
从undo与redo日志,理解事务底层ACID底层原理
- 事务特性
- 原子性:当前事务操作要么同时成功,要么同时失败。原子性由undo log日志来保证。
- 一致性:使用事务的最终目的,由业务代码正确逻辑保证。(由原子性、隔离性和持久性共同保证)
- 隔离性:在事务并发执行时,他们内部的操作不能互相干扰。
- 持久性:一旦提交了事务,它对数据库的改变就应该是永久性的。持久性由redo log日志来保证
事务四大隔离级别
- 事务隔离级别
InnoDB如何解决脏读、不可重复读和幻读的?
在InnoDB中,通过MVCC解决脏读和不可重复读,通过MVCC+间隙锁解决幻读的。
MVCC多版本并发控制机制,Mysql在读已提交和可重复读隔离级别下都实现了MVCC机制。
事务底层锁机制和MVCC并发优化机制
串行化底层实现机制
串行化底层是加了读锁的
读已提交和可重复读底层实现
MVCC机制详解
每张表都有trx_id:事务id,roll_pointer:回滚指针,指向undolog表
- 在insert的时候,undolog表会存一条delete语句:delete t where t.id=dddd
- 在update的时候用到了copy on writer机制(写时复制,写的复制一份副本),undolog表会存一条之前的数据,读写分离,不阻塞,写的时候在副本的基础上写,读还是读的老数据,这个就作为历史数据存到undo log表里
可重复读实现机制:多个版本的undlolog日志链,查询的时候在第一次读的时候会跟查询到的那条数据有一个绑定关系,来实现一个可重复读以后再读的时候就读绑定的那条数据
怎么去绑定的?
啥叫读写不阻塞?
比如一条数据,读写同时进来,写的时候会复制一份副本,在副本的基础上来进行写,而读读的是老的原数据,这个时候读写分离同时进行。
脏写问题(重要)
现在还有一个问题?如果绑定是老的数据用老的数据去做操作,但是库里已经更新成了新的数据比如事务要操作余额字段 版本绑定的500,新版本的数据是1000,现在用500做操作,给余额加200,此时余额变成700,此时去更新这条数据。把1000给覆盖掉了 这就是脏写。脏写的问题该如何解决??
- 可以使用乐观锁来解决,加个版本号
更新的时候,如果发现版本号不一致就重新读一条来进行更新操作,如果还不相等,那就继续读新数据来更新
读已提交?实现机制
也是MVCC,每次读都读到多个版本中最后那个已经提交的数据
BufferPool缓存与redo日志是如何提升事务性能的