MYSQL MVCC 实现 与 UNDO 的注意事项

2021-05-27 00:00:00 数据 操作 版本 事务 空间

MVCC mulit version concurrency control , 在每个传统数据库上基本上都有实现,近突然问了自己一句,MYSQL 是怎么实现的这个功能,好像明白又说不清,那自己就来复习一下,MYSQL 到底是怎么来完成这个功能的。

下面是一段MVCC的简单释义:

Multi version concurrency control (mvcc)Concurrency control is achieved by saving a snapshot of data at a certain point in time. That is to say, no matter how long the transaction is executed, the data seen inside the transaction is not affected by other transactions. According to the start time of the transaction, each transaction may see different data for the same table at the same time.


多版本的控制MVCC 主要功能是保存一个时间的数据,通过保存这个时间点的数据,让事务无论在何时执行,他所看到的数据,不会受到外部的其他的事务的影响, 根据开始时间的不同,每个事务都会拥有自己那个执行时间点所得到的数据状态.


In short,Multi version concurrency controlThe idea is to save the historical version of the data, and realize the concurrency control of the database by managing multiple versions of the data row. In this way, we can determine whether the data is displayed or not by comparing the version number. When reading the data, we do not need to lock it, which can also ensure the isolation effect of transactions.

 
换句话,MVCC 主要服务的是,通过保存历史的版本的数据, 当事务读取数据的时候,不会被锁定,并通过隔离级别的设定, 让不同的事务去读取不同事务版本的数据行信息.


________________________________________________________________

那么MVCC 主要解决的问题是避免读和写之间 BLOCK, 让 读 和 读的操作可以并行, 让读和写的操作可以并行.  所以死锁一般都是发生在  写和写之间的操作, 并且可以通过此方法解决读版本一致性的问题. 


MYSQL 实现多版本控制的基础是,MYSQL是具有UNDO表空间的, INNODB 仅仅查看数据行的版本. 低于当前系统的行的事务版本. 保证读取的行在此事务之前存.

这里插入数据会产生一个当前的行的事务的版本号, 删除行则会将当前的事务的版本号,变为删除的标记.  UPDATE的操作主要的在多版本控制中采用插入和删除的两个操作来进行UPDATE的操作执行.


MYSQL的MVCC 支持 READ COMMIT 和 REPEATABLE READ 的方式,其他两种方式 READ UNCOMMIT 的方式,的问题在于读取了所有的新的行,而Serializable 的问题在于读取的行都是被锁定的行.



这里undo logs 分为两个部分, 1  INSERT UNDO LOG  2  UPDATE UNDO LOG,  2种不同的LOG的功能不同.   INSERT UNDO LOG  主要的功能在于插入后的数据回滚,在数据插入并 COMMIT 后,会立即将undo log 中的信息抛弃掉, UPDATE 的位置的UNDO LOG 信息除了作为回滚数据使用,还作为一致性读使用,也就是支持MVCC 中的数据读取的作用,


这里如果进行比较大的事务操作,会导致undo log 膨胀,并且如果不及时的进行commit的操作则UNDO 空间不会被释放,而即使commit后,UNDO 表空间的数据的清理也不是立即的,也是需要通过 purge 线程进行处理的, 如果过大的连续的大事务,也会造成UNDO 表空间无法快速清理, 让UNDO 表空间的使用变得紧张.

如何计算一个MYSQL中可以使用多少undo的回滚段,(一个回滚段一个事务),按照下面的公式.

(innodb_page_size / 16) * innodb_rollback_segments * number of undo tablespaces

通过这个公式可以观察到,通过添加undo 的表空间可以增加MYSQL服务器中并发的事务的支持.

除此以外我们还应该知道我们的MYSQL在某一个时刻是否可以支撑的并发的事务数量。

(innodb_page_size / 16 / 2) * innodb_rollback_segments * number  undo tablespaces

举例我们的文件有三个的情况下,3*128/2= 192 也就是同一个时刻我们的数据库可以并行支持192个事务同时操作。


MYSQL 8.023 的UNDO LOG的初始大小通过  innodb_max_ undo_ log_ size  值的 25% 来设定,初始的大小,默认为两个文件 undo001  undo002.


从MYSQL 8.014 开始可以创建UNDO表空间并指定文件名


 create undo tablespace  undo_name add datafile '文件名.ibu'


影响UNDO表空间的几个性能的几个因素


1  UNDO 表空间的数量和UNDO 文件的数量

2   负责undo 表空间操作的磁盘的性能

3   应用程序中事务的大小的情况

4   事务的并发量和UNDO PURGE线程的设置和工作情况


在 MYSQL 8.016 这个版本的MYSQL中可以通过下面的语句来对MYSQL 进行UNDO LOG truncation 性能的监控

SELECT NAME, SUBSYSTEM, COMMENT

FROM INFORMATION_SCHEMA.INNODB_METRICS

WHERE NAME LIKE '%truncate%';





相关文章