一, MySQL 可重复读级别下, 因为 MVCC 引起的 BUG, 下图 1 为相应的 Java 代码, 其中事务 1 的生命周期最长, 循环开启的事务 2,3,4... 与事务 1 并行 , 数据的读取只会成功一次, 后面的读不到新增数据, 从而出现空指针异常, 但是当事务隔离级别为读提交时, 程序会正常执行
图 1
解决方案: 将方法 userRemoteService.addUser 和 UserBaseContext.getUserBaseByUserId 放在两个方法中, 避免事务的并发问题
二, MVCC 简介: Multiversion Concurrency Control, 多版本并发控制机制, 行级锁的一个变种, 但是它在很多情况下避免了加锁操作, 因此开销更低, 实现了非阻塞的读操作, 只在 read committed 和 repeatable read 两个隔离级别下工作, 因为 read uncommitted 总是读取最新的数据行, 而 serializable 则会对所有读取的行都加锁
三, 数据行隐藏字段
6 字节的 DATA_TRX_ID 标记了最新更新这条行记录的 transaction id, 每处理一个事务, 其值自动 + 1
7 字节的 DATA_ROLL_PTR 指向当前记录项的 rollback segment 的 undo log 记录, 找之前版本的数据就是通过这个指针
6 字节的 DB_ROW_ID, 当由 innodb 自动产生聚集索引时, 聚集索引包括这个 DB_ROW_ID 的值, 否则聚集索引中不包括这个值., 这个用于索引当中
DELETE BIT 位用于标识该记录是否被删除, 这里的不是真正的删除数据, 而是标志出来的删除. 真正意义的删除是在 commit 的时候
对于有有三个字段 id,name,balance 的表, 其中 id 为主键, 实际的拥有的列如下
图 2
四, 具体的执行过程:
SELECT:Innodb 检查每行数据, 确保他们符合两个标准:
1,InnoDB 只查找版本早于当前事务版本的数据行 (也就是数据行的版本必须小于等于事务的版本), 这确保当前事务读取的行都是事务之前已经存在的, 或者是由当前事务创建或修改的行
2, 行的删除操作的版本一定是未定义的或者大于当前事务的版本号, 确定了当前事务开始之前, 行没有被删除
符合了以上两点则返回查询结果.
INSERT:InnoDB 为每个新增行记录当前系统版本号作为创建 ID, 该操作没有回滚指针, 因为不存在历史版本
DELETE:InnoDB 为每个删除行的记录当前系统版本号作为行的删除 ID.
UPDATE:InnoDB 复制了一行. 这个新行的版本号使用了系统版本号. 它也把系统版本号作为了删除行的版本
事务执行过程中, 只有在第一次真正修改记录时 (比如使用 INSERT,DELETE,UPDATE 语句), 才会被分配一个单独的事务 id, 这个事务 id 是递增的, 下面以 update 为例说明
begin-> 用排他锁锁定该行 -> 记录回滚数据到 undo log-> 将修改前的行标记为删除, 写事务编号 -> 新增行保存修改后的值, 写事务编号, 回滚指针指向 undo log 中的修改前的行 -> 记录修改后数据 redo log->commit-> 后台线程将数据写磁盘
图 3
优点:
保存这两个额外系统版本号, 使大多数读操作都可以不用加锁. 这样设计使得读数据操作很简单, 性能很好.
缺点:
每行纪录都需要额外的存储空间, 需要做更多的行检查工作, 以及一些额外的维护工作.
五, read view
1. 判断当前版本数据项是否可见
2. 提交读的隔离级别下, 事务开始后到结束前, 每次读取数据都会生成一个 read view, 而可重复读的隔离级别, 只有事务开始后第一次读取数据, 才生成 read view
2. 在 innodb 中, 每创建一个新事务, 存储引擎都会将当前系统中的活跃事务列表创建一个副本 (read view), 副本中保存的是系统中当前不应该被本事务看到的其他事务 id 列表
3. 当用户在事务中要读取某行记录的时候, innodb 会将该行当前的版本号与该 read view 进行比较
4. 比较流程: read view 中最早的事务 id 为 tmin, 最迟的事务 id 为 tmax, 当前事务 id 为 t0
图 4
参考文章
- https://www.cnblogs.com/williamjie/p/9492810.html
- https://www.jianshu.com/p/db334404d909
- https://juejin.im/post/5c9b1b7df265da60e21c0b57
来源: http://www.bubuko.com/infodetail-3100942.html