聊聊数据库中的 savepoint

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 故事要从全局二级索引开始讲起。 当我们构建了一个全局二级索引之后,一条逻辑上的数据插入,就会变成两条物理上的数据插入:一条插入到主表,另一条插入到索引表。为了保证主表和索引表数据的一致性,我们往往需要开启分布式事务,再并行地插入两条数据。如果其中一条数据插入失败了,比如索引上出现了唯一键冲突,但主表的数据已经插了进去,怎么办呢?

作者:勿遮  本文来源:PolarDB-X知乎号

从全局二级索引讲起

故事要从全局二级索引开始讲起。 当我们构建了一个全局二级索引之后,一条逻辑上的数据插入,就会变成两条物理上的数据插入:一条插入到主表,另一条插入到索引表。为了保证主表和索引表数据的一致性,我们往往需要开启分布式事务,再并行地插入两条数据。如果其中一条数据插入失败了,比如索引上出现了唯一键冲突,但主表的数据已经插了进去,怎么办呢?当然,我们可以简单粗暴地回滚整个事务,来保证数据的一致性。 但有的时候,我们已经在事务里执行了大量的操作,这时候仅仅因为一条数据的插入失败,就要回滚整个事务,代价实在太大。对于单机 MySQL 来说,如果出现了这种插入 UK 报唯一键冲突的情况,会自动回滚这条插入的语句。至于是忽略报错继续执行事务,还是回滚整个事务,则交给业务方来决定。作为一款全面兼容 MySQL 的分布式数据库,PolarDB-X 自然也要具备这种特性。 其实,不只是全局二级索引的情况,其他场景比如 batch insert/delete/update、广播表 DML 等都可能会遇到这种情况。

聊聊 savepoint

如果要回滚单条或多条语句,而非回滚整个事务,我们自然想到使用 savepoint 这一功能。在事务中,我们可以随时设置一个 savepoint,后续再回滚到这个 savepoint,从而回滚 savepoint 后的所有操作。 MySQL 是如何实现 savepoint 能力的呢? MySQL 在 server 层中,对每个事务对象维护了一个 savepoint 的链表,用于记录这个事务设置过的 savepoint 对象。其中,每个 savepoint 对象主要记录了 savepoint 的名字,用于标识不同的 savepoint 对象。 在设置一个 savepoint 时,会往链表末尾插入一个 savepoint 对象。在释放一个 savepoint 时,会根据 savepoint 名字遍历链表,找到对应的 savepoint 对象,将其及其后面的所有 savepoint 删除。在回滚一个 savepoint 时,会找到对应的 savepoint 对象,根据其存储的信息进行回滚操作,随后,还会隐式释放掉其后的所有 savepoint(不包括它自己)。 可以看到,每个 savepoint 对象都需要存储一定的信息,来告诉 binlog 和 innodb 需要回滚到什么位置。对于 binlog 记录的是设置 savepoint 时的 binlog cache 的 offset;对于 innodb,则是设置 savepoint 时 undo log 的 undo number。这两个简单的信息,就足够 binlog 和 innodb 完成回滚操作了。 事实上,innodb 内部还维护了事务的 savepoint 链表,但本质上和上述说的链表没什么太大差异,就不展开讨论了。

使用 savepoint 解决问题

那 PolarDB-X 该如何使用 DN 的 savepoint 解决一开始提到的全局二级索引的问题呢? 其实做法也很简单,我们只需要在任何物理语句执行之前,加上一个 savepoint,在所有物理语句执行之后,视情况来回滚或是释放 savepoint。我们将这一行为称为 auto-savepoint。 其实,innodb 的行为也是如此,其在每条语句前(实际是上一条语句执行后),会更新一个匿名的 savepoint 对象 last_sql_stat_start,其保存了上一条语句执行后的 undo number。在当前语句执行出错时,通过这个 undo number 来回滚掉这条语句的操作。 熟悉 PolarDB-X 的同学一定知道,PolarDB-X 通过物理连接(计算节点到存储节点的连接)来执行物理 SQL。对于一条逻辑更新 GSI 的 SQL 语句,可能需要使用 2 条物理连接,执行 3 条物理 SQL(一条主表 update,一条 GSI 表删除,一条 GSI 表插入)。如下所示:

物理连接 0(物理分库 0): 
update primary_tb; insert gsi_tb; 
物理连接 1(物理分库 1): 
delete gsi_tb;

设置 auto-savepoint 的关键就在于要在合适的时机设置 savepoint。在这个例子中,任何一个物理连接执行出错,都会通知其他连接中断其正在执行的操作。假设在物理连接 1 执行 delete gsi_tb 的时候报错了,我们不知道物理连接 0 上的具体执行情况。哪些语句执行成功了、哪些语句执行失败了、哪些语句还没开始执行,我们都不知道。此时,我们可以借助 savepoint 的能力,不管具体的执行情况如何,都统一回滚到一切操作还没开始做的状态,就能达到回滚单条逻辑 SQL 的效果。 因此,我们自动设置的 savepoint 行为就是:

物理连接 0(物理分库 0): 
savepoint `s0`; update primary_tb; insert gsi_tb; rollback to savepoint `s0`;
物理连接 1(物理分库 1): 
savepoint `s0`; delete gsi_tb (ERROR); rollback to savepoint `s0`;

当然,这里面的设计还会保证参与了一条逻辑 SQL 的所有物理连接都正确设置上 savepoint,以保证 savepoint 的设置和回滚都不会漏掉,否则就会出现数据不一致的问题了。

代价是什么

我们通过 DN 的 savepoint 能力,来实现 CN 层面上的回滚单条语句的功能。尽管从前面的讨论来看,设置和释放 savepoint 的代价都比较低,只是在链表上新增或删除一个元素,但我们还是需要在实现上尽量减轻这种代价。 首先,我们尽量避免 savepoint 的设置,只在涉及 GSI 或其他逻辑执行的 DML 时,才自动设置 savepoint。因为只有在逻辑执行下,才可能发生分片间不一致的场景,才需要 auto-savepoint 来保证逻辑语句的原子性。其次,我们设置和释放都是通过多语句的方式,将 savepoint 的 SQL 和业务产生的物理 SQL 一并下发,避免增加额外的 RTT。最后,我们还使用了私有协议绕过 savepoint SQL 的解析过程,直接在 DN 上调用设置和释放 savepoint 的代码。


云原生数据库PolarDB分布式版新增标准版形态,基于X-Paxos提供100%兼容MySQL的高可靠性集中式数据库服务。

阿里巴巴集团双十一同款数据库,即刻拥有!

相关实践学习
跟我学:如何一键安装部署 PolarDB-X
《PolarDB-X 动手实践》系列第一期,体验如何一键安装部署 PolarDB-X。
相关文章
|
4天前
|
存储 数据库
为什么需要数据库
为什么需要数据库。
18 4
|
4天前
|
数据库
数据库视频(一)
数据库视频(一)
12 0
|
8月前
|
关系型数据库 Linux BI
数据库的一些知识
数据库的一些知识
29 0
|
4天前
|
数据库
数据库(二)
数据查询教程包括单表查询操作,如Select语句用于选取属性,可指定列名、使用别名、计算表达式,并通过Distinct去除重复元组。条件查询(Where子句)支持比较运算,如Between、In、Like(支持模糊匹配)及空值判断。连接查询用于合并多表数据,如内连接、外连接和笛卡尔积。例如,通过连接emp和dept表,可获取员工姓名及其所在部门名称。
15 3
|
4天前
|
关系型数据库 MySQL 数据库
数据库(三)
数据完整性是数据库管理中的关键概念,确保数据的准确和一致。主要包括: 1. 实体完整性:通过主键(唯一且非空)来标识表中的每条记录,如创建`test2`表时设置`n1`为主键。 2. 创建表`test3`时,`n1`和`n2`组合成为主键,确保多字段的唯一性。 3. 唯一约束:用于保证列值的唯一性,如在`test1`中添加对`n2`的唯一约束,或创建`test4`时`n1`和`n2`的组合值唯一。 4. 引用完整性:通过外键约束实现,如`emp`表的`dept_id`引用`dept`表的`id`,确保数据间的关联合法性。外键可以有级联操作,如`on delete cascade`和`o
13 0
|
4天前
|
存储 关系型数据库 MySQL
数据库(一)
登录MySQL数据库的命令是`mysql -u用户名 -p密码`,其中`-u`后面接用户名,`-p`后面接密码。如果服务器不在本地,还需指定`-h`参数加上IP地址或域名,以及可选的`-P`参数指定端口号。创建数据库使用`create database 数据库名`,查看数据库用`show databases;`。数据类型包括整数类型(如int)、字符串(如char、varchar、text)、日期时间类型(如date、time、datetime)等。数据库操作还包括创建表、修改表结构、删除表以及数据的增删改查操作。数据恢复和备份涉及mysqldump工具及source命令来导入导出数据。
11 1
|
4天前
|
存储 数据库 数据安全/隐私保护
数据库特点
数据库特点
34 9
|
4天前
|
存储 NoSQL 关系型数据库
数据库
数据库
86 5
|
10月前
|
存储 SQL 数据库
数据库—耿建玲视频总结(三)
其实这章很是简单的,索引(编号),其中讲解了索引的优缺点;以及都有什么类别的索引,最后就是如何建立。
|
10月前
|
数据库
数据库1-3章小总结
数据库1-3章小总结
33 0

热门文章

最新文章

http://www.vxiaotou.com