1. 分布式事务评测缘起
近段时间,一直在参与国内金融行业的分布式数据库选型测试工作,围绕银行内部的实际业务场景进行验证。遇到了一个比较有意思的案例。
前期在联机业务场景测试中,各大数据库厂商在事务测试上都比较顺利,在功能和性能角度都很好的满足了业务要求。 但在跑批业务场景的测试中,个别数据库厂商就遇到了分布式事务的一致性问题(会读到分布式事务中间状态的数据),而该厂商通过了行业的各项事务测评认证,因此展开了如何有效评测国产数据库事务一致性的话题,需要大家辩证的思考下。
本文是系列文章的第一篇,介绍第一个重要话题:“数据库的分布式事务”,这也是目前普通用户面对分布式数据库产品介绍问的最多的一个内容,如何有效评测分布式事务也是一个非常重要的能力。致敬同行,我们将PolarDB-X事务架构设计上的一些思考和测试方式,做了整理和梳理,期望能对大家更好的理解分布式事务的测试有所帮助。
这些所谓观点并无谁对谁错之分,仅仅代表我们的思考。如果你有任何想说的,也欢迎在评论区与我讨论。
2. 金融行业通用测评
近年来国内自主可控诉求越来越强烈,国内数据库行业蓬勃发展,诞生了很多创业型公司,国家层面也出台了一系列的数据库评测标准,大体分为集中式和分布式数据库的测评。 中国人民银行在2020年发布了一个行业标准,《分布式数据库技术金融应用规范 技术架构(JR/T 0203-2020)》 关于分布式事务测试的描述:
分布式数据库金融标准,是分布式数据库行业中最完整的标准之一,给出了对于分布式数据库的事务ACID测试的指导性意见。
机构测试设计的测试用例,普遍会采用模拟数据库故障方式来验证分布式事务,细分一下场景:
- 模拟数据库多副本的重启,可以验证数据库事务的持久性 (ACID中的D)
- 模拟主机的异常故障(断网、IO Hang等),可以验证数据库事务的原子性 (ACID中的A)
- 采用SQL交互,设置不同的数据隔离级别,开多个链接,手工验证事务的隔离级别 (ACID中的I)
- 比如运行TPC-C 或者 特定的转账测试,在数据导入完成、以及程序运行完成后,运行几条一致性校验的SQL来验证数据的一致性 (ACID中的C)
整个测评方案更多是围绕事务ACID,进行了比较全面的覆盖型验证,但从数据库内核研发的视角视角、以及金融行业实际业务场景的实测来看,还是有一定的局限性,否则也不会出现通过分布式数据库金融行业认证,但无法通过金融行业实际业务场景的测试验收。
3. PolarDB-X的设计和思考
3.1 事务是一切的基础
先抛开分布式数据库,我们首先思考一个通用数据库的话题: 数据库事务在哪些地方影响了业务使用? 我们拿一个银行的转账场景做一下例子:A账户余额有100元,B账户余额0元,在这个基础上A向B转账40元 复盘常见的业务场景:
- 在线联机业务,通过事务ACID机制,需要保证A向B转账过程中的数据一致性,满足任意时刻A和B上的账户总余额为100
- 数据库备份和恢复,按时间点的恢复(point-in-time recovery)目前也是行业的共识需求,我们需要确保恢复出来的备份集数据,满足A和B上的账户总余额为100
这也是目前行业测试过程中常见的关注场景,但结合业务场景思考一下,还远不止,比如:
- 跑批业务,典型的ETL机制,通过数据的全量读取和批量写入,为满足业务处理效率,很多数据库厂商会提供旁路导入和导出的机制,同样需要满足事务的总余额为100。旁路导出例子:select * from user partition(p1) order by id desc limit 10,10,每个分片数据单独做分页排序,减少分布式的分页排序代价。
- flashback query,典型的数据快速恢复场景,oracle基于MVCC多版本提供了AS OF Timestamp语法,可以快速读取一个历史的事务数据版本,结合insert into xxx select xx as of timestamp '10分钟前'可以快速恢复出业务误操作的数据。
- 读写分离 or follower read,典型的技术架构场景,比如paxos/raft的三副本,很多数据库厂商会提供follower read的能力,本质上就是一种读写分离的架构,同样需要满足事务的总余额为100。需要注意:事务的一致性读 和 多副本下的数据复制延迟带来的数据不一致读,这是两个不同的概念。比如;数据延迟只是让我们读到1秒钟之前的事务数据,但1秒前的数据读取总余额时也要为100,不能读到40或者140的中间状态
- 容灾架构(两地三中心、同城3AZ),典型的容灾架构场景,比如考虑两地三中心的极端场景,中心地域挂了,切换到异地机房,异地机房的数据可以有延迟(RPO>0),但需要事务粒度的一致性,满足A和B上的账户总余额为100
- 主备复制 or CDC(mysql binlog订阅),典型的数据增量复制的场景,常见于数据库的binlog增量日志,部署异地多活复制,同样需要需要保证事务的一致性,在外置复制增量数据的情况下,满足A和B上的账户总余额为100(查询数据仓库 或者 异构的备库)
- HTAP架构,常见的数据库实现为采用多份数据副本的方式,通过行转列构建异步的列存副本,虽然数据行转列会有延迟,但查询到列存副本时同样需要考虑事务的一致性,即使读取1秒前的数据也要满足总余额时为100。
大家可以辩证的思考一下,这部分的业务场景在传统的单机数据库事务中是一个默认能力,但在分布式事务中绝不是一个简单的ACID机制,还需要有更多的顶层设计,一句话总结:事务是一切的基础,影响重大
举一个反例子来看,常见于传统的分库分表的事务架构,可以通过开源MySQL或者PG的主备强复制、两阶段的事务提交,可以一定程度的满足ACID的定义,但在遇到其他业务场景会事务一致的局限性:
- 指定时间的备份恢复,因缺少任意时间点的一致性视图,导致无法满足一致性恢复。变种的方法:定时做高频的一致性快照,比如每各30秒备份一次全局活跃事务链表,可以达到恢复到30秒的粒度
- 联机和跑批混合场景,跑批场景读取全量数据过程中,因缺少一致性的视图,会有机会读取到事务提交阶段的状态。变种的方法:跑批场景不能做旁路,全量数据拉取都得经过全局活跃事务链表来判断
3.2 分布式事务方案
目前分布式事务常见方案:
简单做一个解读:
- XA协议,全名为 X/Open XA 协议,是一项通用的事务接口标准,最早在90年代开始提出,可参考:《Distributed Transaction Processing: The XA Specification》。注意:XA主要基于2PC两阶段提交实现事务的原子性,而分布式下的一致性则需要额外的设计,会出现读偏斜的问题
- GTM,最早起源于PG-XC开源数据库,主要是通过GTM分配一个事务ID,通过活跃事务链表来解决事务的可见性问题。目前常见于PG生态,比如GaussDB,活跃事务链表在单机数据库中也比较常见。
- TSO/HLC,主要是基于时间戳技术,参考Oracle的MVCC多版本设计,每个事务都有start_ts / end_ts的时间戳,通过时间戳的先后顺序来判断事务的可见性,相比于活跃事务链表会更轻量。 TSO和HLC主要还是对于时间戳分配算法上的一些差异,目前来看海外数据库重点关注GEO Partition带来的多活架构。
PolarDB-X 事务设计上的总结:
一、事务的主链路(在线联机业务的ACID)
a. 持久性:Paxos多数派,通过共识协议确保主机故障时RPO=0,不丢中间数据
b. 原子性:2PC + XA,通过两阶段提交,确保事务的原子性
c. 隔离性 & 一致性:TSO + MVCC,通过时间戳版本号 + MVCC多版本,实现跨分片的数据一致性读
关于PolarDB-X的一些事务设计,可以参考我们之前的文章:
- PolarDB-X 强一致分布式事务原理
- PolarDB-X 分布式事务的实现(一)
- PolarDB-X 分布式事务的实现(二)InnoDB CTS 扩展
- PolarDB-X 分布式事务的实现(三):异步提交优化
二、数据库的备份恢复 / flashback query
按时间点的恢复(point-in-time recovery),通常诉求是通过指定一个物理时间,PolarDB-X在分布式事务设计上,允许将物理时间转化为事务的TSO时间戳,通过分布式事务的TSO来做数据库的精确恢复边界。
flashback query,也算一种特殊的数据恢复场景,通过AS OF TIMESTAMP指定一个物理时间,PolarDB-X会将物理时间转化为事务的TSO时间戳,基于分布式事务的MVCC多版本来实现对历史版本的数据读取。
比如:分布式事务的TSO,是有42位的物理实践 + 16位的逻辑时间戳组成,可以通过位移快速实现物理时间戳和TSO时间戳的转化。
参考文档:PolarDB-X 备份恢复
三、联机&跑批 混合场景
联机场景主要是简单的查询和写入为主的高并发业务,非常容易基于分布式多节点来达到线性扩展。而跑批场景更多是围绕数据的批量处理,需要最大化的利用分布式多节点资源的并行性,期望跑批也能达到线性扩展的性能。 PolarDB-X跑批场景最佳实践设计上,我们引入了数据旁路hint能力,业务可以通过该hint进行快速的旁路数据导入和导出,随着DN节点数量的扩容,整体跑批容量和吞吐能力可以达到线性增加。 PolarDB-X在面向跑批场景的分布式事务设计上,引入业界oracle通用的2PC + MVCC事务机制
- 支持undo/redo,事务中间数据通过undo提前落盘,可以支持GB级别的超大事务
- 计算存储彻底分离,MVCC的事务上下文(undo/buffer、可见性判断等)全部落在存储节点DN上,计算节点CN只承担分布式事务协调者的状态,可以确保在旁路导入导出时数据存储DN节点的数据一致性。区别于Spanner/Percolator等事务模型、以及基于GTM的事务机制。
四、同构多副本(读写分离、容灾架构场景)
分布式下的多副本,一般会按照multi-raft/paxos的进行分组,同一个分组会复用一个多数派日志流,而不同的分组会有独立的多个日志流,每个日志流会因为各自的复制进度产生一些差异。
PolarDB-X在多副本架构下的事务设计上,引入了强一致读写分离的机制:
- 如下图所示,不同副本会因为日志流的复制进度不同而产生差异,需要在读写分离访问副本时进行识别和处理
- 分布式事务的上下文,需要在多副本架构下进行数据事务状态的复制,确保在多副本中事务数据的一致性
五、事务增量日志 (CDC增量复制、HTAP行转列)
传统数据库会提供CDC机制(Change Data Capture),在mysql生态里主要就是binlog,下游可以通过定于binlog来实现增量数据同步或者消费。
PolarDB-X在事务增量日志设计上,参考了mysql binlog的协议和格式:
- 记录分布式事务的上下文,比如事务中DML的提交顺序、事务TSO时间戳等,将这些状态数据持久化到单个DN的局部增量日志中
- 引入CDC全局日志组件,基于分布式事务的TSO时间戳进行多个DN局部日志的汇总、合并和排序,生成最终的binlog增量日志流
3.3 增强版转账测试
PolarDB-X 结合众多业务的实际使用场景,我们在典型银行转账测试的场景基础上,增强了场景正交组合测试,可以帮助大家更快、更有效的评测分布式事务。 说明:本测试重点针对ACID中的一致性C场景的测试,事务持久化、原子性的测试,可以复用行业通用测试中的模拟故障来进行验证。
银行转账测试的技术模型抽象
不断随机选取两个账户 A/B,然后模拟 A 账户给 B 账户转账。每一笔转账在数据库中如下图所示:
其中,balance 表示余额,version 表示该账户完成了多少笔转账。在备库一致性读的验证中,我们除了会验证总余额必须一致外,还会先开启事务查询主库所有账户,再开启另一个事务查询备库的所有账户,并确保备库上看到的每个账户 version 值,必须不小于主库中该账户的 version 值,即备库不能产生延迟。
内置数据库测试场景
整体测试设计围绕金融行业的典型场景,进行组合验证分布式事务的一致性。 比如:模拟联机和跑批场景的组合、跑批场景中直连备库(满足联机和跑批的资源强隔离)、以及跑批场景指定访问某时刻的数据(比如,访问历史某时刻的数据,进行数据ETL处理后恢复误操作的数据)
测试场景 | 场景描述 | 备注说明 |
联机流量 | N个线程并发的模拟转账 | 背景流量,通过随机两个分片之间的转账才产生分布式事务 |
常规一致性场景 | M个线程通过select * from xx,读取所有数据后再内存计算总余额,并验证数据的一致性 | 模拟事务在主副本上并发写和读,确保事务一致性 |
跑批场景 | M个线程通过旁路hint导出(指定hint访问select * from xx),读取所有分片的所有数据后在内存计算总余额,并验证数据的一致性 | 模拟事务在主副本上并发写,模拟跑批的旁路hint操作,确保事务一致性 |
flashback query | M个线程通过select * from xx AS OF TIMESTAMP ’xx' 访问历史某一刻的所有数据后在内存计算总余额,并验证数据的一致性 | 模拟事务在主副本上并发写,模拟数据恢复场景的读操作,确保事务一致性 |
备副本一致性读 (又名:读写分离) 高级特性:备库强一致读 (replica_strong_consistency=true) |
M个线程访问分布式的备副本,通过select * from xx,读取所有数据后再内存计算总余额,并验证数据的一致性如果开启备库强一致读,会检查写后读的可见性,通过行记录里的业务version进行判断 | 模拟事务在主副本上并发写,模拟读写分离访问备副本,确保事务一致性 |
跑批场景 + 备副本一致性 | M个线程访问分布式的备副本,通过旁路hint导出(指定hint访问select * from xx),读取所有数据后在内存计算总余额,并验证数据的一致性 | 模拟跑批场景,通过备副本来实现资源隔离,同时需要确保事务一致性 |
flashback query + 备副本一致性 | M个线程访问分布式的备副本,通过select * from xx AS OF TIMESTAMP ’XX' 访问历史某一刻的所有数据后在内存计算总余额,并验证数据的一致性 | 模拟数据恢复,通过备副本来实现资源隔离,同时需要确保事务一致性 |
跑批场景 + flashback query | M个线程通过通过旁路hint导出(指定hint访问,select * from xx AS OF TIMESTAMP ’XX'),访问历史某一刻所有分片的所有数据后在内存计算总余额,并验证数据的一致性 | 模拟跑批场景,通过flashback query来实现日切卸数等类似场景,同时需要确保事务一致性 |
跑批场景 + flashback query + 备副本一致性 | M个线程访问分布式的备副本,通过旁路hint导出(指定hint访问,select * from xx AS OF TIMESTAMP ’XX' ),访问历史某一刻所有分片的所有数据后在内存计算总余额,并验证数据的一致性 | 模拟跑批场景,通过flashback query来实现日切卸数等类似场景,通过备副本来实现资源隔离,同时需要确保事务一致性 |
外置组合测试场景
整体测试设计围绕金融行业的测试标准,通过组合一些额外的人肉操作来验证PolarDB-X数据库实例以外的事务一致性。
测试场景 | 场景描述 | 备注说明 |
指定时间点的备份恢复PITR(point-in-time recovery) | 1.启动转账程序15分钟2.备份集指定时间点恢复,时间点T选择为转账程序运行过程中的某一个时间3.待备份集恢复完成后,人工检查数据一致性 | 通过模拟联机场景,验证备份恢复后数据的一致性。1.检查最新一条记录(order by time desc limit 1)的时间戳,与恢复的预期时间T值,满足<=1秒。2.统计总余额,select sum(balance),满足数据一致性 |
事务增量复制(CDC日志) | 1.启动转账程序,并保持持续运行2.配置数据库增量复制,比如将PolarDB-X数据增量同步到MySQL 3.增量复制过程中,人工检查数据一致性 |
通过模拟联机场景,验证下游事务增量日志的数据一致性 1. MySQL的主备复制,会基于PolarDB-X binlog进行回访,通过验证select sum(balance)的总余额,来验证是否满足数据一致性 |
3.4 如何运行测试
PolarDB-X提供了转账测试工具,通过docker一键启动即可快速完成验证,快速配置可以适配特定数据库的语法,从而满足对数据库厂商的分布式事务验证。 比较典型的组合场景:联机场景 + 跑批场景 + 备库一致性(将跑批场景的ETL调度到备库上,在满足事务一致性下,实现联机和跑批业务的互相隔离)
测试场景设计:
安装数据库
1.PolarDB-X安装
# 使用virtual environment python3 -m venv venv source venv/bin/activate # 安装pxd pip install -i https://mirrors.aliyun.com/pypi/simple/ pxd
创建polardbx.yaml文件
version: v1 type: polardbx cluster: name: pxc-tryout-new gms: image: polardbx/polardbx-engine:latest engine: galaxy engine_version: "8.0" host_group: [127.0.0.1] resources: mem_limit: 4G cn: image: polardbx/polardbx-sql:latest replica: 1 nodes: - host: 127.0.0.1 resources: mem_limit: 8G cpu_limit: 4 dn: image: polardbx/polardbx-engine:latest engine: galaxy engine_version: "8.0" replica: 1 nodes: - host_group: [127.0.0.1, 127.0.0.1, 127.0.0.1] resources: mem_limit: 8G cdc: image: polardbx/polardbx-cdc:latest replica: 1 nodes: - host: 127.0.0.1 resources: mem_limit: 4G
通过pxd create创建实例,建议主机规格>=8C32G (压测工具会产生一定的并发压力)
pxd create -f polardbx.yaml
2.部署其他数据库(比如:开源的单机MySQL),作为PolarDB-X CDC同步到的下游数据库
# 部署mysql 8.0.32 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -v /etc/localtime:/etc/localtime -d mysql:8.0.32 --default-authentication-plugin=mysql_native_password --gtid_mode=ON_PERMISSIVE --enforce_gtid_consistency=OFF # 配置PolarDB-X CDC和MySQL的复制关系,指定PolarDB-X的账号和密码 docker exec -it some-mysql bash mysql -h127.0.0.1 -uroot -p123456 > CHANGE MASTER TO MASTER_HOST='10.0.0.102', MASTER_USER='polardbx_root', MASTER_PASSWORD='', MASTER_PORT=xxx, MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=4; # 启动主从复制 > start slave ; > show slave status;
3.登录PolarDB-X数据库,创建测试库 transfer_test:
基于步骤1返回的连接串,快速登录PolarDB-X:
mysql -h127.0.0.1 -uroot -pxxxx # 创建PolarDB-X数据库 > create database transfer_test mode = auto # 开启PolarDB-X的follower read(副本读) > set global ENABLE_FOLLOWER_READ=true;
创建测试库后,可以登录单机MySQL实例看下是否正常同步了transfer_test库,如果看到了库说明整体复制链路就正常了
测试工具使用
1.拉取镜像
docker pull polardbx/transfer-test:latest
2.准备配置文件 config.toml,假设存放于 /tmp/transfer-config/config.toml ,以下是一个示例:
# 主库的数据源, 格式: '${user_name}:${password}@tcp(${ip}:${port})/${db_name}' dsn = 'polardbx_root:123456@tcp(127.0.0.1:8527)/transfer_test' # 账户数量 row_count = 100 # 每个账户的初始余额 initial_balance = 1000 # 建表语句后缀,适配不同的分布式数据库 create_table_suffix = 'PARTITION BY HASH(id) PARTITIONS 4' # 数据库加强特性:备库强一致读 (查询follower副本或者备库场景,是否强制校验写后读的数据一致性) # 比如:主库写了一条测试记录并更新version=100,查询路由到备库后,对应的读操作需要确保一定读到业务测试的写,保证读到的version>=100 replica_strong_consistency = true # 模拟转账,构造分布式事务 [transfer_simple] enabled = true threads = 10 # 场景1. 正常在线查询,校验主库的数据一致性 [check_balance] enabled = true threads = 2 # 场景2.使用hint模拟跑批任务,校验主库的数据一致性 [session_hint] enabled = true threads = 2 # 场景3:使用flashback query模拟数据恢复,校验主库一致性 [flashback_query] enabled = true threads = 2 # flashback 到 (min_seconds, max_seconds) 秒之前 min_seconds = 10 max_seconds = 20 # 场景4. 查询follower副本或者备库,校验副本的数据一致性 [replica_read] enabled = true threads = 2 # 加在 SQL 语句前的 hint,对于 PolarDB-X,该 hint 可以强制查询路由到备库 replica_read_hint = '/*+TDDL:SLAVE()*/' # 备库数据源,对于PolarDB-X和主库dsn保持一致即可,如果测试其余数据库的备库,可以通过指定备库的连接串 replica_dsn = 'polardbx_root:123456@tcp(127.0.0.1:8527)/transfer_test' # 场景2和4的组合,使用hint查询follower副本或者备库,校验组合场景的数据一致性 [replica_session_hint] enabled = true threads = 2 # 加在 SQL 语句前的 hint,对于 PolarDB-X,该 hint 可以强制查询路由到备库 replica_read_hint = '/*TDDL:SLAVE()*/' # 备库数据源,对于PolarDB-X和主库dsn保持一致即可,如果测试其余数据库的备库,可以通过指定备库的连接串 replica_dsn = 'polardbx_root:123456@tcp(127.0.0.1:8527)/transfer_test' # 场景3和4的组合,使用 flashback query查询follower副本或者备库,校验组合场景的数据一致性 [replica_flashback_query] enabled = true threads = 2 # 加在 SQL 语句前的 hint,对于 PolarDB-X,该 hint 可以强制查询路由到备库 replica_read_hint = '/*+TDDL:SLAVE()*/' # 备库数据源,对于PolarDB-X和主库dsn保持一致即可,如果测试其余数据库的备库,可以通过指定备库的连接串 replica_dsn = 'polardbx_root:123456@tcp(127.0.0.1:8527)/transfer_test' # flashback 到 (min_seconds, max_seconds) 秒之前 min_seconds = 10 max_seconds = 20 # 场景5,校验数据库通过CDC同步到下游数据库,通过链接下游数据库,检查数据一致性 [check_cdc] enabled = true threads = 2 # 下游 MySQL(或其他 DB)数据源 downstream_dsn = 'root:123456@tcp(127.0.0.1:3306)/transfer_test'
[session_hint] 和 [flashback_query] 都开启,还会额外测试场景 2 和 3 的组合,使用 flashback query + session hint 进行测试,校验组合场景下主库的数据一致性。 [replica_session_hint] 和 [replica_flashback_query] 都开启,还会额外测试场景 2、3、4 的组合,使用 flashback query + session hint + 备库读进行测试,校验组合场景下备库的数据一致性。
3.导入数据,注意替换配置文件存放目录
docker run --rm -v /etc/localtime:/etc/localtime \ -v #配置文件存放目录#:/tmp \ polardbx/transfer-test:latest prepare -config=/tmp/config.toml 示例: docker run --rm -v /etc/localtime:/etc/localtime \ -v /tmp/transfer-config:/tmp \ polardbx/transfer-test:latest prepare -config=/tmp/config.toml
如果上一步配置了 127.0.0.1 作为数据库 ip,容器运行需要加上 --network host 参数。
4.观察测试结果 (如果满足事务一致性会持续运行,不满足一致性会立即终止)
2023/04/13 08:45:27 all partitions: p1, p2, p3, p4 2023-04-13T08:45:27.364Z INFO transfer/app.go:30 App start 2023-04-13T08:45:37.364Z INFO transfer/main.go:349 TPS check_balance: 30.90 2023-04-13T08:45:37.365Z INFO transfer/main.go:349 TPS flashback_query: 0.00 2023-04-13T08:45:37.365Z INFO transfer/main.go:349 TPS flashback_session_hint: 0.00 2023-04-13T08:45:37.365Z INFO transfer/main.go:349 TPS session_hint: 16.50 2023-04-13T08:45:37.365Z INFO transfer/main.go:349 TPS transfer_simple: 180.40 2023-04-13T08:45:47.364Z INFO transfer/main.go:349 TPS check_balance: 0.00 2023-04-13T08:45:47.364Z INFO transfer/main.go:349 TPS flashback_query: 0.00 2023-04-13T08:45:47.364Z INFO transfer/main.go:349 TPS flashback_session_hint: 0.00 2023-04-13T08:45:47.364Z INFO transfer/main.go:349 TPS session_hint: 0.00 2023-04-13T08:45:47.364Z INFO transfer/main.go:349 TPS transfer_simple: 0.00 2023-04-13T08:45:57.364Z INFO transfer/main.go:349 TPS check_balance: 58.20 2023-04-13T08:45:57.364Z INFO transfer/main.go:349 TPS flashback_query: 157.90
运行测试过程中,数据库show full processlist的截图:
3.5 通用数据库场景的验证
测试场景 | MySQL | PolarDB-X | TiDB |
联机场景 | 正常 | 正常 | 正常 |
跑批场景 | 正常 | 正常 | 正常(不支持hint导出单个分片数据) |
flashback query | / | 正常 | 正常 |
备副本一致性读 (读写分离) |
有限正常(不支持备库强一致读) | 正常 | 正常 |
跑批场景 + 备副本一致性 | 有限正常(不支持备库强一致读) | 正常 | 正常 (不支持hint导出单个分片数据) |
flashback query + 备副本一致性 | / | 正常 | 正常 |
CDC同步到其他数据库 | 正常 | 正常 | 正常 |
指定时间点恢复 | 正常 | 正常 | 正常 |
4. 最后
分布式事务的评测模型,目前行业的通用评测重点聚焦于模拟数据库故障(验证了事务的原子性和持久性),数据库事务的隔离性和一致性测试,主要也以SQL功能隔离级别的功能测试为主,缺少比较健壮且有效的测试方法。 同时在面向实际业务场景测试中,前期大家关注焦点也是常见的联机事务ACID(很多数据库厂商的事务方案也是针对性的设计),最后在关联了上下游业务后才发现国产数据库在事务机制上的缺陷性。
最后,从数据库内核研发的角度来看,分布式事务的一致性,会作为非常重要的基础能力,除了数据库内核的ACID机制外,同时也会涉及:读写分离多副本、备份恢复一致性、两地三中心容灾切换、CDC事务增量日志等多个场景的一致性问题,不要迷恋任何国产数据库的介绍,可以通过更有技巧性的事务一致性测试来验证(可以辅助常见的主机故障模拟),基于联机和跑批的组合场景,实现国产数据库事务的有效评测。
本文来源:PolarDB-X知乎号
本文作者:七锋、勿遮