A-A+

InnoDB源码解析-事务系统

2022年02月04日 数据库 暂无评论 阅读 330 次

InnoDB事务系统负责InnoDB层事务管理,快照管理,MVCC等。

事务对象

InnoDB层事务对象为 struct trx_t 类型。

InnoDB的事务开启序,每个读写事务启动时获取一个id,事务结束时获取no作为提交序。

事务状态包含:

  • TRX_STATE_NOT_STARTED
  • TRX_STATE_FORCED_ROLLBACK
  • TRX_STATE_ACTIVE
  • TRX_STATE_PREPARED
  • TRX_STATE_COMMITTED_IN_MEMORY(COMMITTED)

 

常规的事务状态变换:NOT_STARTED -> ACTIVE -> COMMITTED -> NOT_STARTED。

 

TRX_STATE_PREPARED是针对XA事务的prepare状态。

 

所有的事务都会存放在mysql_trx_list链表中,这是一个双向链表,本身不支持并发,需要trx_sys->mutex保护。

 

read_view是该事务的快照,我们后面会详细描述这块。

 

commit_lsn跟redo提交有关,我们在InnoDB log sys中介绍。

 

事务对象管理

事务对象管理分为两块,一块是活跃的读写事务集合,一块是所有活跃事务集合(包括读写事务和只读事务)。

所有活跃事务集合以链表形式存储,也就是mysql_trx_list。

活跃的读写事务集合非常重要,存放在trx_sys->rw_trx_ids,它跟快照关系密切,实际上也只是为了快照才维护了这个数据结构。

 

 

快照

如前所说,InnoDB是开启序,写事务开启后申请到一个id,事务修改了某一行,会在行头写入对应的事务id,以后该行可能被其他并发事务读取,至于能不能看到该行的这个新版本,取决于读事务的快照是否认为写事务已经提交。可能存在id小的写事务一直没提交,但id大的事务先提交了,所以对快照来说,创建快照时刻的活跃事务列表就成了数据版本可见性的依据,也就是快照的一部分。

快照的定义如下:

 

申请一个快照的过程:

  • 获取一个view对象,可以从free view list拿一个复用,或者分配一个新的
  • 将活跃读写事务列表复制到view->m_ids
  • m_low_limit_id为当前已经分配出去的最大trx id
  • m_low_limit_no为已经分配了提交序no的事务中最小的(遍历serialisation_list列表),如果列表为空,则与m_low_limit_id相等。
  • m_up_limit_id为view->m_ids中最小值,如果view->m_ids为空,m_up_limit_id也等于m_low_limit_id

上述过程在trx_sys->mutex保护下进行。

 

 

快照对象的管理

所有已经open的快照都在 MVCC::m_views列表中保存,该列表也由trx_sys->mutex保护。

为了避免反复分配释放快照对象,如果快照对象close时,先还到MVCC::m_free这个free list中。

purge等地方需要用到当前系统中最老的快照。获取最老快照实现方式 MVCC::get_oldest_view 是在MVCC::m_views中找第一个已经open的快照,这个过程也是在trx_sys->mutex保护进行。

之所以可以直接取列表第一个open的read view,是因为在trx_sys->mutex锁的同步下,快照的创建完全是串行化的,时间上越早创建的快照越在MVCC::m_views前面。

 

 

给我留言