mysql的innodb引擎itl_MVCC

MVCC

MVCC

目录

MVCC如何实现

旧版本数据延迟清除的原因

快照读(一致性读)的用途

MVCC总结

Mysql MVCC实现

Innodb的事务的相关概念

Innodb多版本的实现

Innodb的事务的提交与回滚

Oracle的多版本实现

ITL解释

ITL内容

Oracle数据块的结构

Oracle的多版本实现

旧版本的数据在回滚段中的结构

PostgreSQL MVCC实现

PostgreSQL事务ID

PostgreSQL MVCC实现

比较事务新旧的方法

可见性判断

借助wiki上的解释:

Multiversion concurrency control (MCC or MVCC), is a concurrency control method commonly used by database management systems to provide concurrent access to the database and in programming languages to implement transactional memory.

MVCC如何实现

? 简单说,就是更新数据时,保留原先版本的数据, 即一行数据存在多个版本。

? 实现方法: – 回滚段的实现方法(Oracle、MySQL Innodb的实现方 法) – 在原先的数据文件中的旧版本数据不删除,生成新版 本的数据(PostgreSQL的实现方法)

? 通常与事务的功能集成在一起:

? 但MVCC时事物回滚或提交之后,旧版本的数据 仍然需要保留一段时间,是延迟清除的。

旧版本数据延迟清除的原因

? 就是为了提供快照读(一致性读)的功能

? 对于Read Commited隔离级别:需要保证当开始 执行一个SQL之后,这个SQL是读一个不变的快 照的数据,即使在这个SQL执行过程中有其它的事务提交了,这些提交的数据对于这个SQL也是 看不到了,这样保证了数据的一致性。

? 对于Read Repeatable隔离级别:从这个事务开 始之后,看到的数据就是一个不变的数据,执行 相同的SQL总是可以看到相同的数据。所以叫"可重复读"

快照读(一致性读)的用途

如果没有MVCC的解决方案

MVCC总结查询和更新、删除、插入操作互相不阻塞

? 当开始一个查询后,读到的数据总是查询 开始时那个时间点的快照

在查询开始后,发生的变更(即使已提交), 这次查询也是看不到的。

一个事务无论运行多长时间,看到数据都是相 同的

不同开始时间的事务中相同的查询,返回的数 据也可能不同

Mysql MVCC实现

Innodb的事务的相关概念

? redo log – 在变更数据之前,把变更先记录到一个文件中, 称为redo log

? undo log – 与redo log相反,undo log是为回滚而用

? rollback segment – 在Innodb中,undo log被划分为多个段,具体 某行的undo log就保存在某个段中,称为回滚 段。

Innodb多版本的实现

事务1:insert t(id, col1,col2,col3,col4) values(23,'a1','b1','c1','d1');

Innodb的事务的提交与回滚

提交与回滚

– 当事务正常提交时,Innodb只需要更改事务状 态为COMMIT即可,不需做其他额外的工作

– Rollback需要根据当前回滚指针从undo log中 找出事务修改前的版本,并恢复。

? 如果事务影响的行非常多,回滚则可能会很慢,根 据经验值没提交的事务行数在1000~10000之间, Innodb效率还是非常高的,大量的回滚效能会影响。

? 回滚时,也会产生redo日志 – Innodb的COMMIT效率高,Rollback代价大

Innodb的可见性判断

? InnoDB表会有三个隐藏字段

– 6字节的DB_ROW_ID

– 6字节的DB_TX_ID

? InnoDB内部维护了一个递增的tx id counter,其当 前值可以通过show engine innodb status获得

– 7字节的DB_ROLL_PTR(指向回滚段的地址)

可见性比较的方法:

– 并不是用当前事务ID与表中各个数据行上的事 务ID去比较的

– 在每个事务开始的时候,会将当前系统中的所 有的活跃事务拷贝到一个列表中 (read view), 根据read view最早一个事务ID和最晚的一个事 务ID来做比较的,这样就能确保在当前事务之 前没有提交的所有事务的变更以及后续新启动 的事务的变更,在当前事务中都是看不到的。

– 当然,当前事务自身的变更还是需要看到的。

Oracle的多版本实现

? Oracle也是通过回滚段来实现多版本的 – 但Oracle的实现更复杂,更精细一些。

? Oracle中也有事务ID,但不是递增的

– Undo Segment Number + Transaction Table Slot Number + Wrap

? 与innodb不一样的地方:

– 事务信息并不是记录在每个数据行上的,而是 在块头中的ITL槽上,所以相对来说更省空间

ITL解释

? ITL(Interested Transaction List)在Oracle 数据块的头部

– ITL记录在一个数据块中有多条,每一条itl可 以看作是一个记录,每条记录常被称为槽位 (itl slot)

– 一个itl slot只可以记录一个事务的信息,如果 这个事务已经提交或回滚了,那么这个itl的 位置就可以被反复使用。

? 每个数据块上itl槽的多少可以动态创建, 建表时可以指定: – initrans:每个数据块默认ITL槽数目,默认 为2 maxtrans:每个数据块最多的ITL槽数,最 大255

ITL内容

Oracle数据块的结构

旧版本的数据在回滚段中的结构

PostgreSQL MVCC实现

什么?PostgreSQL没有回滚段!!!

– 是的,没有回滚段。旧数据是放在原有数据文 件中的

– 如果放在原有的数据文件中,旧数据越来越多 怎么办?

? 垃圾回收操作vacuum来做这个事。

? 有自动垃圾回收autovacuum

? 更新操作中新行的物理位置发生了变化, 非更新列的索引是不是也要更新?

– 通常不会,HOT技术。如果原有的数据块之间 有空间,旧行与新行之间会建一个链接,索引 上仍然指向旧的数据行。

? 垃圾回收的代价会不会影响性能?

? 有很多参数控制这个影响:vacuum_cost_delay, vacuum_cost_limit

? 实现方法

– 每行上有xmin和xmax两个系统字段

– 当插入一行数据时,将这行上的xmin设置为当 前的事务id,而xmax设置为0

– 当更新一行时,实际上是插入新行,把旧行上 的xmax设置为当前事务id,新插入行的xmin设 置为当前事务id,新行的xmax设置为0

– 当删除一行时,把当前行的xmax设置为当前事 务id

– 当读到一行时,到commitlog中查询xmin和 xmax对应的事务状态是否是已提交还是回滚了, 就能判断出此行对当前行是否是可见。

– autovacuum进程会把一些不要的旧行清理掉

PostgreSQL事务ID

? 与innodb类似,是一个递增的数字,常常 被称为xid

– 但是一个无符号的32bit的数字表示

? 如何知道事务是提交了还是回滚了?

– 事务的状态记录一个叫commitlog的位图文件 中,即pg_clog目录下的文件中

– 每个事务的状态用两个bit来表示:

– #define TRANSACTION_STATUS_IN_PROGRESS 0x00

– #define TRANSACTION_STATUS_COMMITTED 0x01

– #define TRANSACTION_STATUS_ABORTED 0x02

– #define TRANSACTION_STATUS_SUB_COMMITTED 0x03

PostgreSQL MVCC实现

? 事务ID到达最大的一个数字后,怎么办?

– 到大最大后,又重新开始,

– 此问题被称之为事务ID回卷问题(Transaction ID Wraparound) ? 记录事务的commitlog文件会不会不断的增 大?

比较事务新旧的方法

– 普通事务的比较方法:(int32) (id1 - id2) < 0

– 表达式算出来值为真,则id1比id2更旧一些, 为假则id1比id2新 ? 例子:id1=4294967294,经过4个事务,id2=5, id1-id2=4294967289,而4294967289因大于2^31, 转成int32后会变成一个负数,表过式为真,所以id1 比id2更旧

– BootstrapXID比所有其它事务都旧,包括 FrozenXID

– FrozenXID比普通事务旧

可见性判断

? 与innodb一样,事务开始时,会把当前活 跃的事务ID记录到一个列表中,这称之为 快照。

? 系统先通过判断t_xmin是否在全局活跃事务 列表中、是否在事务快照活跃事务列表中、 根据事务提交日志判断事务是提交还是回 滚了等来判断t_xmin事务是否在事务开始时 已经提交

MVCC相关教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值