IT评测·应用市场-qidao123.com

标题: 数据库MVCC详解 [打印本页]

作者: 伤心客    时间: 2025-3-20 20:00
标题: 数据库MVCC详解
MVCC

1.基本介绍

数据库:MySQL。【很多主流数据库都使用了MVCC,比如MySQL的InnoDB引擎、PostgreSQL、Oracle】
MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。是数据库管理系统中的一种并发控制方法。
MVCC的基本原理:  它通过保存数据的历史版原来实现,这样读操作不会被写操作壅闭,写操作也不会被读操作壅闭。这样的话,进步了并发性能。比如说,当一个事务开始读取数据时,它会看到数据库在某个时间点的快照,之后纵然其他事务修改了数据,这个事务看到的还是旧版本的数据,直到它提交或者回滚。
不同的隔离级别(如读已提交、可重复读、串行化)在MVCC中的实现方式不同。例如,在读已提交级别下,每次读取都会获取最新的快照,而可重复读则是在事务开始时确定快照,后续读取都基于这个快照,从而避免不可重复读的问题。

MVCC就是为了实现读-写冲突不加锁,而这个读指的就是快照读, 而非当前读,当前读实际上是一种加锁的操作,是灰心锁的实现
当前读  灰心锁;      快照读  乐观锁?
2.mvcc实现原理

数据库不知道的秘密。
每行记录除了我们自定义的字段外,另有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段
① MVCC 核心机制

②示例

有这样一张表,内里有记录。
idnameageDB_TRX_IDDB_ROLL_PTR1Alice251000x0000初始版本由事务 txid=100 提交生成;DB_ROLL_PTR 指向旧版本(初始为 NULL)。
这个时候有两个事务来了。
事务A 更新数据,InnoDB引擎,会为这行数据创建一个新版本,并修改 DB_TRX_ID=200,DB_ROLL_PTR 指向旧版本(事务100提交的版本)。
这个时候,还没有A事务还没有提交,新版本(V2)还未提交,旧版本(V1)仍旧存在。
  1. id | name  | age | DB_TRX_ID | DB_ROLL_PTR     【这个是新版本V2】
  2. ---|-------|-----|-----------|------------
  3. 1  | Alice | 26  | 200       | 0x1234(指向旧版本V1)
  4.                                  丨丨
  5.                                  丨丨
  6.                                   ↓
  7. id | name  | age | DB_TRX_ID | DB_ROLL_PTR     【这个是旧版本V1】
  8. ---|-------|-----|-----------|------------
  9. 1  | Alice | 25  | 100       | 0x0000
复制代码
然后,事务B读取数据,事务B 启动时会生成一个 ReadView,记录当前活跃事务的 ID 列表。假设此时只有事务A(txid=200)未提交,活跃事务列表为 [200]
事务B 根据 ReadView 判定数据版本的可见性:
故,事务B读到的如下:
  1. id | name  | age
  2. ---|-------|-----
  3. 1  | Alice | 26  
复制代码
可以看到上述读写,好像没有加锁。。
③可见性规则

InnoDB 判定数据版本是否可见的逻辑如下:
MVCC 通过维护数据多版本和 ReadView 机制,实现读写不壅闭和高并发:
这种机制在包管事务隔离性的同时,极大提升了数据库并发性能。
3.补充知识点

MySQL 中的 undo logredo logbinlog 是三种核心日志,各自承担不同的职责,共同保障数据库的事务性、恒久性和高可用性
下面三个是参考deepseek的解释。
① Undo Log(回滚日志)

作用
工作机制
见上面的mvcc。
② Binlog(二进制日志)

作用
工作机制
我来举个例子:
  1. -- 事务C: 删除一行数据
  2. BEGIN;
  3. DELETE FROM users WHERE id = 1;
  4. COMMIT;
  5. -- 提交后,binlog 记录该 DELETE 语句(或行变化)。从库读取 binlog 并重放,保持数据一致性。
复制代码
③ Redo Log(重做日志)

作用
工作机制
我来举个例子:
  1. -- 事务B: 插入一条新数据
  2. BEGIN;
  3. INSERT INTO users (id, name) VALUES (2, 'Bob');
  4. COMMIT;
  5. -- 提交时,redo log 记录插入操作的物理页修改,之后数据可能还未写入磁盘。
  6. -- 若此时崩溃,重启后根据 redo log 恢复该插入操作。
复制代码
以更新操作为例子:
1. 为什么需要 redo log 和 binlog 两种日志?
2. undo log 会被删除吗?
3. binlog 和 redo log 的写入顺序?
end.参考

参考:https://www.cnblogs.com/jelly12345/p/14889331.html

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4