LBCC
LBCC
是Lock-Based Concurrent Control
的简称,意思是基于锁的并发控制,此文主要内容是MVCC
,所以LBCC
暂时不展开。
当前读
当前读(Locking Read
)也称锁定读,读取当前数据的最新版本,而且读取到这个数据之后会对这个数据加锁,防止别的事务更改即通过next-key
锁(行锁+gap锁)来解决当前读的问题。
在进行写操作的时候就需要进行“当前读”,读取数据记录的最新版本,包含以下SQL
类型:select ... lock in share mode
、select ... for update
、update
、delete
、insert
。
因为锁的粒度过大,会导致性能的下降,因此提出了比LBCC
性能更优越的方法MVCC
。
MVCC
MVCC
是Multi-Version Concurremt Control
的简称,意思是基于多版本的并发控制协议,通过版本号,避免同一数据在不同事务间的竞争,只存在于InnoDB
引擎下。它主要是为了提高数据库的并发读写性能,不用加锁就能让多个事务并发读写。
MVCC
的实现依赖于:三个隐藏字段、Undo log
和Read View
,其核心思想就是:只能查找事务id小于等于当前事务ID的行;只能查找删除时间大于等于当前事务ID的行,或未删除的行。
接下来让我们从源码级别来分析下MVCC
。
隐藏列
MySQL
中会为每一行记录生成隐藏列,接下来就让我们了解一下这几个隐藏列吧。
(1)DB_TRX_ID:事务ID,是根据事务产生时间顺序自动递增的,是独一无二的。如果某个事务执行过程中对该记录执行了增、删、改操作,那么InnoDB
存储引擎就会记录下该条事务的id。
(2)DB_ROLL_PTR:回滚指针,本质上就是一个指向记录对应的undo log
的一个指针,大小为 7 个字节,InnoDB
便是通过这个指针找到之前版本的数据。该行记录上所有旧版本,在undo log
中都通过链表的形式组织。
(3)DB_ROW_ID:行标识(隐藏单调自增 ID
),如果表没有主键,InnoDB 会自动生成一个隐藏主键,大小为 6 字节。如果数据表没有设置主键,会以它产生聚簇索引。
(4)实际还有一个删除flag隐藏字段,既记录被更新或删除并不代表真的删除,而是删除flag变了。
undo log
每当我们要对一条记录做改动时(这里的改动可以指INSERT、DELETE、UPDATE),都需要把回滚时所需的东西记录下来, 比如:
- Insert undo log :插入一条记录时,至少要把这条记录的主键值记下来,