1 MVCC 解决什么问题
消除数据库读事务与写事务之间的锁以提升性能,并保证数据一致性。
2 MVCC是什么
Multiversion concurrency control (MCC or MVCC) 是一种数据库并发控制机制。关系型数据库需满足 ACID,否则会数据不一致,产生脏读幻读。保证数据一致性常用手段是加锁,但加锁会引起吞吐性能问题,尤其对一些耗时事务。
MVCC 旨在通过对同一份数据保持多版本来同时解决一致性和性能问题。
在 MVCC 中,每个用户看到的都是一份独立的 snapshot,用户的改动在完全提交以前,只有自己能看到。
MVCC 写数据时,并非覆盖现有数据,而是创建一份新数据,所以数据库中会存在同一份数据的多个版本。
MVCC 需要定期清理旧版本数据,以最新版本数据替换主数据。清理过程 stop-the-world。
MVCC 读通常需要一个 timestamp 或者 transaction id 来告诉数据库要读取的版本。
通过以上机制,读与写事务完成隔离(isolation),并且不需要加锁。所以读是永远不被block。
但如果有多个写事务同时发生,则可能发生冲突,这时需要通过乐观锁来解决。
wiki原话:every object (P) has a Timestamp (TS), however if transaction Ti wants to Write to an object, and the transaction has a Timestamp (TS) that is earlier than the object's current Read Timestamp, TS(Ti) < RTS(P), then the transaction is aborted and restarted. (This is because a later transaction already depends on the old value.) Otherwise, Ti creates a new version of object P and sets the read/write timestamp TS of the new version to the timestamp of the transaction TS=TS(Ti).[2]
3 并发读写
Time=1 时,状态如下,T1 写入 Object1 为 "Hello",事务 commit 后,T0 版本被垃圾回收。
Time | Object 1 | Object 2 |
---|---|---|
0 | "Foo" by T0 | "Bar" by T0 |
1 | "Hello" by T1 |
T1 提交后,有一个长时事务 T2 开始读取 Object 1 和 Object 2 的数据,期间,有 T3 事务删除 Object 2,并添加 Object 3="Foo-Bar"。
Time=2 时,状态如下:
Time | Object 1 | Object 2 | Object 3 |
---|---|---|---|
0 | "Foo" by T0 | "Bar" by T0 | |
1 | "Hello" by T1 | ||
2 | (deleted) by T3 | "Foo-Bar" by T3 |
于是 Object 2 有了版本 2 (deleted by T3)。T2 和 T3 并发。T3 事务造成的数据版本对 T2 不可见,T2 仍读取 Time=1 时的 Object 2 数据("Bar" by T0)。
4 其他相关文章
https://blog.csdn.net/bigtree_3721/article/details/68942273
https://blog.csdn.net/Return_True_hang/article/details/60334801
https://blog.csdn.net/chosen0ne/article/details/18093187
https://blog.csdn.net/gao_yu_long/article/details/73739559
https://blog.csdn.net/whoamiyang/article/details/51901888
https://blog.csdn.net/libo222/article/details/52469547
https://vladmihalcea.com/how-does-mvcc-multi-version-concurrency-control-work/