mysql的事务隔离概念

InnoDB默认隔离级别为可重复读,更新数据的时候使用当前读。他们都是在内部视图的基础支持的基础上完成的。下面会记录一些mysql的事务回滚和事务启动时机也记了一些在官方手册上撸下来的概念

#事务隔离

1
2
3
4
5
6
7
mysql> CREATE TABLE `t` (
`id` int(11) NOT NULL,
`k` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1,1),(2,2);

事务A 事务B 事务C
start transaction with consistent snapshot;
start transaction with consistent snapshot;
update t set k=k+1 where id=1;
update t `set k=k+1 where id = 1;
select k from t where id=1;
select k from t where id = 1;
commit;
commit;

事务A显示 1
事务B显示 3

事务的启动时机

上面例子中用到 start transaction with consistent snapshot这和传统的begin/commit最大的区别是,前者事务的启动时机是运行时创建视图执行,后者是begin后的第一条语句执行后创建视图。

MVCC是什么

在mysql官方文档中可以看见

innoDB 是一个多版本储存引擎,它保持行的信息修改版本,它自持事务特性入如并发和回滚。这些信息在表空间名为回滚段的数据结构里(rollback segment)InnoDB使用回滚段中的信息来进行回滚操作,它还保持了这些信息可以恢复到老版本实现一致性读

在内部,InnoDB给每行储存3个字段放在数据库中。

  • DB_TRX_ID(6byte)

插入,更新的最后一次事务标识,删除在内部是一个更新,将特定的哪一行设置删除标识

  • DB_ROLL_PTR(7byte)

回滚指针指向写入回滚段的undo log,如果信息更新undo log 包含所有更改信息

  • DB_ROW_ID(6byte)

写入新行ID

MVCC 全写是 multiversion concurrency control 多版本并发控制。

快照在MVCC的工作原理

InnoDB在事务之间数据切换依靠一个个的快照,这些快照并不是像数据库备份一样全量记录下来而是依靠一些逻辑关系计算得出。上面有讲到DB_TRX_ID,每次数据提交时都会有个新的数据版本写入undo log并且对应了一个trx_id。

eg:

V1 V2 V3 V4
- set k=10 set k=k+1 set k = k*2
k=1 k=10 k=11 k=22
trx_id=10 trx_id=15 trx_id=17 trx_id=25

按照 事务隔离级别可重复读的定义,一个事务启动的时候,能够看到所有已经提交的事务结果,但是之后这个事务执行期间其他事务的更新它不可见。InnoDB为每个事务构建一个数组,用来记录启动了还未提交的所有ID(包括自己),它利用所有数据都有多个版本实现了MVCC这个能力。

视图的能见度可以总结成

  • 版本未提交,不可见
  • 版本已提交,但是在视图创建后提交,同上
  • 版本已提交,而且在视图创建前,可见

更新逻辑

更新数据是先读后写,而这个读,只能读当前值,称为当前读 。可以理解为更新前会实时读取当前字段的数据修改。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~