亚信安慧 AntDB-M 只读事务提交优化
一、事务操作介绍
数据库系统一般有三种开启和提交事务方法:
配置 autocommit=1 时,隐式开启事务,每执行一条 DML 的 SQL 语句,数据库系统会隐式的自动执行 commit 逻辑提交事务,不需要用户输入 commit 执行提交。
配置 autocommit=0 时,隐式开启事务,随后执行的 DML 的 SQL 语句都在同一个事务内,直到用户输入 commit 执行提交。
用户输入 BEGIN/START TRANSACTION,显式开启事务,随后执行的 DML 的 SQL 语句都在同一个事务内,直到用户输入 commit 执行提交。
在事务开启和提交过程中执行的 DML 的 SQL 语句,申请到的表意向锁资源,根据 2PL 协议会一直持有直到事务提交或回滚才会释放。
如果用户使用 autocommit=0 或 begin 这两种开启事务,执行 DML 的 SQL 语句,未输入 commit 提交事务,在这期间,同时另一个用户执行相同表的 DDL 语句,如果开启事务和执行 DML 的语句是发生在主副本上,DDL 请求会等待超时后失败;如果开启事务和执行 DML 语句发生在备副本上,这时 DDL 语句在主副本上是成功的,DDL 语句通过复制协议同步到备副本上执行,会等待锁超时后失败,导致后续通过复制协议同步过来数据无法继续应用到备副本上,副本间数据同步中断。
二、 现有空闲长事务中止方案
AntDB-M 起初通过配置事务超时间来解决长时间空闲事务未提交带来的事务占用资源未释放的问题,如果空闲事务超时,数据库系统会自动中止事务,执行回滚操作,释放事务资源。
基于空闲事务超时,释放事务资源的方案,有以下缺点:
超时时间配置值不好评估,如果确实有个别应用处理产生的长事务会超过空闲事务超时时间,会影响正常应用流程;
副本数据同步实时性不足,数据丢失风险,如果在在备副本上空闲事务超时时间范围内发生的 DDL 等待失败,副本数据同步中断;如果在 DDL 等待成功(DDL 等锁时间大于空闲事务超时时间),但备副本同步落后。
三、 只读事务提交优化方案
AntDB-M 后续做了进一步的优化,对于只读查询事务长时间未提交,并且数据库的隔离级别是读已提交(Read Committed)时,自动提交查询操作,立即释放事务资源,使并发的 DDL 执行成功,副本数据同步不中断,保证数据库集群稳定。
在数据库隔离级别为读已提交(Read Committed)时,且 autocommit=0 的场景下:
如果事务前序的只读查询操作的 DML,每执行一条只读查询操作的 DML 后,系统自动提交;
如果事务执行过写操作的 DML,之后的再执行只读查询或写操作的 DML,不执行自动提交;
只读查询操作的 DML 有:SELECT 语句(不带 FOR UPDATE);
写操作的 DML 有:INSERT、UPDATE、DELETE、SELECT FOR UPDATE;
对于显式 BEGIN/START TRANSACTION 开始的事务,因为是显式开启事务,认为用户是自知的,不使用此方案。
此方案限定在读已提交(Read Committed)隔离级别,不会影响查询结果的正确性。
四、只读事务提交优化效果演示
演示环境使用 Read-Committed 隔离级别和 autocommit=0。
如图 1 所示,在 set allow_readonly_autocommit=off,关闭只读事务提交优化,只读 SELECT 操作在没有提交事务时会保留一把表意向锁,提交后锁释放掉。
图 1:优化前执行效果
如图 2 所示,在 set allow_readonly_autocommit=on,开启只读事务提交优化,只读 SELECT 操作在事务未提交时也不会持有表意向锁,在 UPDATE 写操作后的只读 SELECT 操作不会释放锁,提交后所有锁都释放。
图 2:优化后执行效果
由此可见,该优化方案可解决备副本上因为只读事务查询操作长时间不提交导致 DDL 执行阻塞或失败问题,避免了数据库集群副本间数据同步落后或中断,提高了 AntDB-M 数据库集群的稳定性。
版权声明: 本文为 InfoQ 作者【亚信AntDB数据库】的原创文章。
原文链接:【http://xie.infoq.cn/article/f38115b65df039230afded82c】。文章转载请联系作者。
评论