MySQL 源码初探3

本文深入探讨了MySQL InnoDB引擎中的MVCC实现,通过源码分析介绍了undo log、rollback segments以及purge线程的工作原理,强调了MVCC在并发控制中的重要性,并提供了简单的执行流程。重点关注了srv0start.cc、srv0srv.cc和trx0sys.h中的关键函数和数据结构。
摘要由CSDN通过智能技术生成

MVCC 简介

在MySQL 5.6 中,默认的隔离级别是 REPEATABLE READ[1],这个级别的隔离可以避免脏读以及不可重复读的问题,但是无法避免幻影读问题。隔离级别越高,事务的并发就会越弱,因此主流的数据库一般选择REPEATABLE READ 或者 READ COMMITTED 作为默认隔离级别。由于默认的隔离级别仍然可能会出现事务并发问题,因此就需要控制并发事务的读写操作。

事务并发控制机制可以分为两大类,一类是Two-Phase Locking(2PL),另一类是Timestamp Ordering(T/O)。采用2PL,事务需要在访问数据前加锁。既然涉及到锁,就有可能会产生死锁。可以采用一些死锁避免、死锁检测的方法处理。最基本的T/O方法根据读写事务的时间戳解决读写冲突[4],并且还需要为涉及到的事务做数据的拷贝,以保证可重复读。从以上两种机制的描述可以看出,采用2PL的方式,在存在大量并发读写事务时,锁争用可能会成为瓶颈;而采用T/O 则可能会涉及到大量的拷贝操作,导致内存资源紧张。

MVCC 属于T/O类并发控制机制,因此会按照时间顺序保存数据的版本。随着系统内事务的运行,保存的数据量会逐渐增大,需要进行清理。T/O类并发控制清理的方式主要有两种,一种是单独运行一个GC线程,另一种是在处理事务扫描数据记录时删除旧版本记录。MySQL 的MVCC采用独立的purge线程清理旧的记录。

MySQL MVCC

MySQL 的InnoDB引擎支持MVCC[5],而其他的存储引擎,比如MyISAM 则不支持。InnoDB 的MVCC 是通过undo log来实现的[8]

根据[6][9] 提到的记录事务read 时可见id范围的read view 结构体以及undo log 文件的组织方式 rollback segment可以大致确定MySQL 中与MVCC实现相关的代码位置。在下图所示的源码文件中可以找到很多undo log、purge 以及rollback segment相关的变量与函数。在storage/innobase/srv目录下的四个源码文件中,srv0conc.cc 主要包含线程控制以及一些atomic 操作相关的函数;srv0mon.cc提供对数据库表、锁相关等信息的统计,涉及到的指标可以查看 storage/innobase/include/srv0mon.h/monitor_id_t。剩下的两个文件srv0start.ccsrv0srv.cc 与本文要介绍的MySQL MVCC的实现的相关性比较大。下面就分别对这两个以及storage/innobase/include/trx0sys.h 中相关的函数和变量做简单介绍。
在这里插入图片描述

srv0start.cc

首先看一下这个源码文件中可能和undo log 相关的函数与变量。

  • srv_undo_space_id_start 根据[9] 关于文件结构的描述,是undo tablespace的起始id,最小是1
    在这里插入图片描述
  • SRV_UNDO_TABLESPACE_SIZE_IN_PAGES 定义tablesspace 占用页面的个数。tablespace 的总大小是固定10MB,页面的大小根据宏定义,UNIV_PAGE_SIZE_DEF 是 16KB,此外还有一个页面最小值 UNIV_PAGE_SIZE_MIN 为 4KB,以及最大值 UNIV_PAGE_SIZE_MAX 为 16KB。
    在这里插入图片描述
  • srv_undo_tablespace_create
  • srv_undo_tablespace_open
  • srv_undo_tablespaces_init
  • srv_start_wait_for_purge_to_start

srv0srv.cc

  • srv_undo_dir 保存rollback 文件的目录路径
  • srv_undo_tablespaces rollback segment 使用的tablespaces 的个数,默认值是8
  • srv_undo_tablespaces_open 被打开并可被使用的tablespaces 的个数,默认值是8
  • srv_undo_logs rollback segments 个数,默认值是1
  • srv_n_purge_threads 在事务提交之后,用于purge rollback segments的线程个数,默认值是1
  • srv_purge_batch_size 一个batch purge的page个数,默认值是20
  • srv_do_purge 清除已提交事务的undo log pages
  • srv_is_undo_tablespace 根据space_id 判断是否是undo tablespace

trx0sys.h

  • trx_sys_t 是事务处理时比较重要的数据结构,在该结构体中包含指向rollback segments 的数组 trx_rseg_t* const rseg_array[TRX_SYS_N_RSEGS],数组中的每个指针指向一个rollback segment。其中 TRX_SYS_N_RSEGS默认值是128。在storage/innobase/include/trx0rseg.h 中包含trx_rseg_t结构体的定义.
    • trx_rseg_t 定义了rollback segment 在内存中的组织方式。结构体中记录了rollback segment的 id、tablespace、占用的page编号等。在该结构体中包含四个列表,分别是update_undo_listupdate_undo_cachedinsert_undo_listinsert_undo_cached。这里按照操作对可见性的要求使用两种list,插入操作使用insert_undo_xxx 、而数据更新和删除则使用update_undo_xxx。这是因为插入的记录在事务提交之前只对当前事务可见,而数据的更新与删除操作则需要维护多版本的信息[9]
      在这里插入图片描述
      • trx_undo_t 结构体的定义在源码文件 storage/innobase/include/trx0undo.h中,作为上面提到的rollback segment的一个slot。结构体的详细定义如下所示。该结构体中记录了该slot 的编号、类型、删除标记、所属事务id、与分布式事务XA Transaction [10]相关的 xid、存放该slot的space以及内存页面相关的信息等。
/** Transaction undo log memory object; this is protected by the undo_mutex
in the corresponding transaction object */

struct trx_undo_t{
   
	/*-----------------------------*/
	ulint		id;		/*!< undo log slot number within the
					rollback segment */
	ulint		type;		/*!< TRX_UNDO_INSERT or
					TRX_UNDO_UPDATE */
	ulint		state;		/*!< state of the corresponding undo log
					segment */
	ibool		del_marks;	/*!< relevant only in an update undo
					log: this is TRUE if the transaction may
					have delete marked records
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值