数据库的并发场景有三种
- 读-读:没有问题
- 读-写:有线程安全问题,可能会造成事务隔离性问题,如:脏读,幻读,不可重复读
- 写-写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失
读 -- 写
多版本并发控制(MVCC)是一种用来解决读-写冲突的无锁并发控制
为事务分配单向增长的ID,为每个修改保存一个版本,版本与事务ID关联,读操作只读该事务开始前的数据库快照。所以MVCC可以为数据库解决以下的问题
- 在并发读取服务器的时候,可以做到在读的时候不用阻塞写操作,也不会被写操作给阻塞,就是一个畅通无阻,提高了数据库并发功能
- 同时还可以解决脏读,幻读,不可重复读等事务隔离性问题,但不能解决更新丢失的问题
理解MVCC:
- Read View
- undo日志
- 3个记录隐藏字段
想要理解MVCC就要从这三个关键字段开始讲起:
3个记录隐藏列字段:
- DB_TRX_ID(6 BYTE):最近(修改/插入) 事务ID,记录(创建这条记录/最后一次修改该记录的事务ID)
- DB_ROLL_PTR(7 BYTE):回滚指针,指向这条记录的上一个版本(指向历史版本,这些数据一般在undo日志中)
- DB_ROW_ID(6 BYTE):隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引
假设一个测试表如下:
mysql> create table if not exists student(
name varchar(11) not null,
age int not null
);
mysql> insert into student (name, age) values ('张三', 28);
Query OK, 1 row affected (0.05 sec)
mysql> select * from student;
+--------+-----+
| name | age |
+--------+-----+
| 张三 | 28 |
+--------+-----+
1 row in set (0.00 sec)
在MVCC看来:
name | age | DB_TRX_ID(创建该记录的事务ID) | DB_ROW_ID(隐式主键) | DB_ROLL_PTR(回滚指针) |
---|---|---|---|---|
张三 | 28 | null | 1 |