MySQL的MVCC
673 字
3 分钟
MySQL的MVCC
MVCC
readview

RC、RR隔离级别在事务开始时会生成一个 readview, 包含以下要素信息
creator_trx_id生成该 readview 的事务的事务idtrx_ids在生成 readview 时当前系统中活跃的读写事务的事务id列表(开启事务但未提交)up_limit_id生成 readview 时 活跃trx_ids 中的最小值low_limit_id生成 readview 时 系统中应该分配给下一个事务的id值有了这个readview,这样在访问某条记录时,只需要按照下面的步骤判断记录的某个版本是否可见
- ==record_trx_id = creator_trx_id== 表明当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问
- ==record_trx_id < up_limit_id== 表明生成该版本的事务在当前事务生成 readview 前已经提交,所以该版本可以被当前事务访问
- ==record_trx_id >= low_limit_id== 表明生成该版本的事务在当前事务生成 readview 后才开启,所以该版本不可以被当前事务访问
- ==record_trx_id between min_trx_id and max_trx_id && record_trx_id not in trx_ids== 说明创建ReadView时生成该版本的事务已经被提交,该版本可以被访问
- ==record_trx_id between min_trx_id and max_trx_id && record_trx_id in trx_ids== 说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被访问
mysql 源码中 readview 结构的说明
struct read_view_struct{ ulint type; /*!< VIEW_NORMAL, VIEW_HIGH_GRANULARITY */ undo_no_t undo_no;/*!< 0 or if type is VIEW_HIGH_GRANULARITY transaction undo_no when this high-granularity consistent read view was created */ trx_id_t low_limit_no; /*!< The view does not need to see the undo logs for transactions whose transaction number is strictly smaller (<) than this value: they can be removed in purge if not needed by other views */ trx_id_t low_limit_id; /*!< The read should not see any transaction with trx id >= this value. In other words, this is the "high water mark". */ trx_id_t up_limit_id; /*!< The read should see all trx ids which are strictly smaller (<) than this value. In other words, this is the "low water mark". */ ulint n_trx_ids; /*!< Number of cells in the trx_ids array */ trx_id_t* trx_ids;/*!< Additional trx ids which the read should not see: typically, these are the active transactions at the time when the read is serialized, except the reading transaction itself; the trx ids in this array are in a descending order. These trx_ids should be between the "low" and "high" water marks, that is, up_limit_id and low_limit_id. */ trx_id_t creator_trx_id; /*!< trx id of creating transaction, or 0 used in purge */ UT_LIST_NODE_T(read_view_t) view_list; /*!< List of read views in trx_sys */};MySQL的RR事务隔离并没有完全防止幻读
可以使用以下例子重现,该例子来自stackoverflow
create table ab(a int primary key, b int);
Tx1:begin;select * from ab; // empty set
Tx2:begin;insert into ab values(1,1);commit;Tx1:select * from ab; // empty set, expected phantom read missing.update ab set b = 2 where a = 1; // 1 row affected.select * from ab; // 1 row. phantom read here!!!!commit;📎 参考文章
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!













