原理介绍
在MySQL OLTP场景下,大量并发的DML语句(Insert, Update, Delete)会访问trx_sys全局结构体中的关键数据结构,导致出现临界区竞争和同步瓶颈。为了解决这个问题,鲲鹏BoostKit对MySQL事务管理器进行了改造,如图1所示,使用无锁哈希表来维护事务单元,读写场景下使用同步锁机制实现事务隔离级别和多版本控制,从而减少锁冲突,提高并发度。
由于MySQL的事务管理器使用链表、数组等数据结构维持全局的事务记录。Trx-sys是MySQL中的一个全局实例,维护事务系统的各种信息,例如几种事务对象的容器。
- rw_trx_list:包含读写事务实例,用链表实现。
- mysql_trx_list:包含所有用户线程事务实例,用链表实现。
- rw_trx_ids:包含读写事务id,用于快速拷贝一个快照,用std::vector实现。
- rw_trx_set:事务id到事务对象的映射,用于通过trx_id快速找到事务实例,用std::set实现。
这些容器本身并不是线程安全的,并且有时需要对Trx-sys里多个数据(包括这些容器和其他数据)进行同步操作。原始代码中使用Trx-sys->mutex实现这一目的。例如trx_set_rw_mode要将一个事务设置为读写事务时:
在高并发写的场景下,系统中存在大量读写事务相关操作,对Trx-sys->mutex的竞争开始形成吞吐量瓶颈。
在Trx-sys->mutex保护的
在本特性中,我们采用无锁哈希对象rw_trx_hash来替代rw_trx_set的功能,从而显著减小Trx-sys->mutex临界区耗时,缓解Trx-sys->mutex竞争,提升系统吞吐量。MySQL本身已经在performance schema和MDL中使用过无锁哈希,原始代码中有LF_HASH实现,可以复用。需要注意的是,虽然访问rw_trx_hash是线程安全的,但由于已经将其相关操作移出临界区,rw_trx_hash与临界区内的数据对象不再同步,需要在代码实现时保证逻辑正确。