什么是MVCC?
MVCC(Multi-Version Concurrency Control)即多版本并发控制,是乐观锁的一种实现方式,在MySql数据库中主要是为了提高数据库的并发性能,做到读写冲突不加锁,这里的读指的是快照读。
快照读与当前读
当前读:读取的记录是最新版本,读取时会对读取的记录加锁,基于悲观锁的原理。加锁的select语句,update,insert,delete使用当前读,其中select语句加读锁,update,insert,delect语句使用的是写锁。
快照读:快照读的前提是隔离级别不是串行级别,在串行级别下的读是当前读,快照读基于MVCC,快照读可能读到的不是最新版本而是历史版本。不加锁的select语句就是使用快照读。
MySql数据库的隔离级别:
读未提交(Read Uncommitted):在其中一个事务中,可以读取到其他事务未提交的数据变化。这种读取其它会话还没有提交的事务,会产生脏读问题。
读已提交(Read Committed):在其中一个事务中,可以读取到其它事务已经提交的数据变化。这种读取可能产生不可重复读问题 。
可重复读(Repetable Read):在其中一个事务中,直到事务结束前,都可以反复读取到事务刚开始时看到的数据,并一直不会发生变化,避免了脏读、不可重复读。
可串行化(Serializable):在每个读的数据行上都需要加上表级共享锁,在每次写数据时都要加上表级排他锁。
只有读已提交和可重复读级别下使用MVCC。
MVCC的实现依赖记录中的3个隐式字段,undo log,Read View
每行记录除了我们自定义的字段外,还有三个数据库添加的隐式字段,DB_TRX_ID
,DB_ROLL_PTR
,ROW_ID
DB_TRX_ID:操作这个事务的id,也就是最后一个对事务进行插入或更新的事务id。
什么是事务id
每开启一个事务,都会从数据库获取一个事务id(也叫做事务版本号),这个事务id是自增的,通过id大小,可以判断事务的时间顺序。
DB_ROLL_PTR:回滚指针,指向这个记录的Undo Log信息。
DB_ROW_ID:如果数据库表没主键,会自动以ROW_ID生成一个聚簇索引。
undo log分为两种:
Read View就是事务进行快照读操作时候产生的读视图。
在该事务进行快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID。
Read View是用来做判断,及当前这个事务能看到的数据是最新的数据还是undo log里的某一个历史版本。
可以把Read View理解成三个全局属性:
trx_list:一个数值列表,用来维护当前活跃的事务id
up_limit_id:记录trx_list列表中活跃的事务id中最小的id
low_limit_id:ReadView生成时刻尚未分配的下一个事务ID,也就是目前出现过最大的事务id+1