一、事务操作介绍 数据库系统一般有三种开启和提交事务方法: 配置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操作在没有提交事务时会保留一把表意向锁,提交后锁释放掉。 640.jpg 图1:优化前执行效果 如图2所示,在set allow_readonly_autocommit=on,开启只读事务提交优化,只读SELECT操作在事务未提交时也不会持有表意向锁,在UPDATE写操作后的只读SELECT操作不会释放锁,提交后所有锁都释放。 640-1.jpg 图2:优化后执行效果 由此可见,该优化方案可解决备副本上因为只读事务查询操作长时间不提交导致DDL执行阻塞或失败问题,避免了数据库集群副本间数据同步落后或中断,提高了AntDB-M数据库集群的稳定性。