PolarDB-X 分区建列类型变更

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 作为一款分布式数据库,变更表的列类型,无论变更的是否是分区键,都需要保证各个分片以及元数据的一致性,因此对于非分区键的列类型变更也不只是简简单单的下推执行就可以的,后续会有一篇文章做详细的阐述,本文主要阐述的是如何对分区键的列类型做变更。

作者:无沐

背景

纵观数据库领域数十年来的发展,关系型数据库脱颖而出的一个重要原因是,它支持用户灵活地定义和修改“数据模型”。

PolarDB-X 作为一款云原生关系型数据库,同样支持通过各种 DDL 语句对数据模型进行修改,以满足用户业务的不断发展,例如:可以使用 ALTER TABLE 语句对表进行添加列,删除列,修改列类型等操作。然而,PolarDB-X 作为一款分布式数据库,其一张逻辑表通常通过某种分区方式将数据划分成多个分片(又称为物理表),并且这些分片分布在不同的数据节点中[1][2],这使得 DDL 语句的实现会更加复杂。

本文以列类型变更为例,简单介绍在 PolarDB-X 中如何执行 ALTER TABLE 语句。首先,列类型变更分为两种:一种是变更分区键列类型,另一种是变更非分区键列类型。对于非分区键的列类型变更,可以直接将逻辑 DDL 拆分成多个物理 DDL,直接下推到对应分片上执行;对于分区键的列类型变更,则相对复杂,在修改列类型的同时,还需要对数据进行重分布,因为分区键列类型修改会影响到分片的路由,如果只是简单的下推执行,会导致使用分区键进行查询时,查询不到数据。

实际上,作为一款分布式数据库,变更表的列类型,无论变更的是否是分区键,都需要保证各个分片以及元数据的一致性,因此对于非分区键的列类型变更也不只是简简单单的下推执行就可以的,后续会有一篇文章做详细的阐述,本文主要阐述的是如何对分区键的列类型做变更。

传统实现

传统分布式数据库中间件采用分库分表的方式对表进行拆分,通常是不允许对拆分键列类型进行变更,如果想要做变更,一般需要重新建一张表,并且停写之后重新导入数据。

如果想要变更的时候不停写,则需要在导入存量数据的同时,自行维护一套双写的逻辑,这种操作方式不仅复杂,而且很难校验最后数据的正确性,导致很容易出现数据不一致的问题。

实现

前文中介绍了PolarDB-X拆分规则变更的实现原理[3],该变更过程同样需要对数据进行重分。

作为数据重分布的经典案例,拆分规则变更过程需经历建新表、双写、导入存量数据、数据校验、流量切换等步骤,整个流程已经非常成熟。很容易想到的是,变更分区键列类型可以基于该流程修改来完成,下面介绍该功能的详细实现。

数据重分布过程中的增量数据双写、存量数据同步以及如何进行流量切换在文章中已经详细描述了,这里不再赘述,强烈建议没有看过的同学,再看一下这篇文章以及 Online Schema Change 这篇论文[4]。

需要补充的一点是,我们还做了基于 TSO 快照[5]的物理数据校验功能,以保证变更前后数据的正确性。 回到本文主题,分区建列类型变更具体与拆分规则变更有以下几点不同,下面详细阐述。

  • 创建新表
  • 对于全局二级索引(GSI)处理
  • 数据校验

创建新表

对于拆分规则变更而言,该功能只会修改分区规则,并不会修改列定义,因此新建表的表结构与原表完全一致,列定义不会做修改。而分区键列类型变更需要修改分区键的列定义,因此新建表的表结构与原表不完全一致,除了分区键的列定义以外其他定义是一样的。

因为新表的列定义与原表的列定义不一致,所以原有的增量数据双写以及存量数据同步流程都存在类型隐式转换,那需不需要对这两个过程做修改呢?答案是不需要的,这是因为对于分区键而言,在 CN(计算节点)上兼容了 DN(数据节点)的类型隐式转换,能够保证使用隐式转换前的数据和隐式转换后的数据都可以路由到同一个分片中,不需要担心路由问题。

另外,熟悉 MySQL 的同学可能知道在 MySQL 中,ALTER TABLE MODIFY COLUMN 的转换和DML的隐式转换逻辑存在差异,这样可能会导致通过 BINLOG 同步的下游与上游数据不一致,这个问题会在数据校验章节进行解答。

全局二级索引处理

文章中介绍了 PolarDB-X 的全局二级索引[6],全局二级索引为了方便回表查询,默认包含了主表的主键以及分区键作为 Cover 列。

为了保证 GSI 和主表数据的一致性,在变更主表分区键列类型时,所有 GSI 的对应 Cover 列的类型也需要同时做变更,因此变更主表的分区键列类型其实会将GSI表的数据也进行重分布。

如果主表的分区键和 GSI 的分区键不一致,且对 GSI 的分区键列类型做变更,为了保证数据的一致性,还是需要走相同流程。

数据校验

为了保证变更的正确性,在创建新表、开启增量数据双写以及存量数据同步都完成之后,需要穿插一个数据校验步骤,数据校验通过之后,才是流量切换以及原表优雅下线过程。

这里先简单介绍一下数据校验的逻辑,首先我们在DN端实现了一种顺序无关的哈希算法并将其封装称为 UDF,在 CN 开始进行校验时,首先利用 TSO 事务获取到源表和目标表的一致性快照,然后分别对源表和目标表对应的 DN 端每个分片进行全表的 hashcheck计算(并行),并将结果拉取到 CN节点汇总,计算出源表的 checksum 和目标表的 checksum,最后进行比较即可。

同构表(分片间并行):

a1.png

异构表(分片间并行):

a2.jpg

对于分区键列类型变更而言,源表和目标表在列定义上不完全一致,直接进行校验肯定会导致校验失败。例如,源表分区键列类型是 VARCHAR,存在一条数据是'123abc',现将分区键列类型修改为 INT,那么目标表分区键对应的数据则转换成了 123,123和'123abc'的 hashcheck值自然是不一样的,因此校验会失败。为了解决上述问题,在创建新表后,为源表添加了一个仅用于数据校验虚拟列(对外不可见),并且该虚拟列是在分区键列的基础上调用列类型转换函数。例如,在上面的例子中,对源表添加一个虚拟列,那么该虚拟列的值即为'123abc'调用转换函数后的结果123,结果与目标表一致。利用添加虚拟列的方式,即可完成数据校验,并且该虚拟列调用的列类型转换函数与 MySQL 中 ALTER TABLE MODIFY COLUMN 转换的处理逻辑一致,因此还可以校验出 DML 隐式转换与 ALTER TABLE MODIFY COLUMN 转换不一致的情况。


查看DDL执行计划


分区键列类型变更并不是一定需要数据重分布,例如对于字符串列类型来说,如果只是想变长,并不修改字符串的 CHARSET 和 COLLATE,那么其实是不需要进行数据重分布的,执行过程与非分区键列类型变更相似。另外,用户可能刚好修改的是 GSI 的分区键列类型,不是主表的分区键,这样仍然会产生数据重分布。可以看到列类型变更其实存在好几种场景,为了便于用户快速区分列类型变更具体是走的什么流程,我们提供了类似 explian 的操作给 DDL语句来使用,下面以sysbench 表举几个例子进行说明。


建表语句:

a3.jpg

例1,修改非分区键列类型:

a4.jpg

例2,修改分区键列类型,并且需要数据重分布:
其中 CREATE TABLE 为创建新表,DROP TABLE 则为完成校验之后删除旧表,ALTER TABLE 为添加虚拟列用于数据校验。

a5.jpg

例3,修改分区键列类型,无需数据重分布:
首先将分区键id列修改为 varchar(30),该过程需要数据重分布,然后再将其类型修改为 varchar(60),explain 结果如下,可以看到无需数据重分布(不需要建表删表)。

20230718135306.jpg

总结


灵活的对表列类型变更是分布式数据库的重要特性。PolarDB-X 支持了分区键列类型变更的同时,保证了数据的强一致、高可用、对业务透明、去除了分布式带来的限制并且使用起来非常方便。本文在 PolarDB-X 拆分规则变更的基础上,简单阐述了实现分区键列类型变更过程中使用到的各项技术点,PolarDB-X 之所以能够支持该功能,使用到了很多诸如 TSO 事务之类的特性,这也是分布式数据库区别于分布式数据库中间件的重要特性之一。


参考文献


[1] PolarDB-X 数据分布解读(一)
[2] PolarDB-X 数据分布解读(二) :Hash vs Range
[3] PolarDB-X 拆分规则变更
[4] Online, Asynchronous Schema Change in F1
[5] PolarDB-X 分布式事务的实现(一)
[6] PolarDB-X 全局二级索引


本文来源:PolarDB-X知乎号

相关实践学习
快速体验PolarDB开源数据库
本实验环境已内置PostgreSQL数据库以及PolarDB开源数据库:PolarDB PostgreSQL版和PolarDB分布式版,支持一键拉起使用,方便各位开发者学习使用。
相关文章
|
4月前
|
SQL 关系型数据库 分布式数据库
PolarDB产品使用问题之相同的SQL语句在不同时间执行EXPLAIN计划显示出不同的索引类型,是什么原因
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
PolarDB产品使用问题之相同的SQL语句在不同时间执行EXPLAIN计划显示出不同的索引类型,是什么原因
|
4月前
|
存储 Oracle 关系型数据库
|
4月前
|
关系型数据库 分布式数据库 数据库
PolarDB产品使用问题之底层是否会自动对数据库表进行分区分表
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
4月前
|
SQL Oracle 关系型数据库
关系型数据库Oracle备份类型
【7月更文挑战第18天】
51 2
|
4月前
|
SQL 存储 关系型数据库
PolarDB-X 原生无锁变更,比 gh-ost 更快、更稳定
无论是单机数据库还是分布式数据库,无锁变更都是非常重要的能力。PolarDB-X 无锁变更技术能够极大提升数据库在线操作的灵活性与安全性,它允许在不影响业务连续性的情况下,对表结构进行修改,如增加列、变更列类型等,这对于全天候无间断服务的业务方来说是至关重要的。
|
4月前
|
存储 关系型数据库 MySQL
|
5月前
|
运维 关系型数据库 Serverless
PolarDB产品使用问题之分区表是否支持2级分区
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
5月前
|
SQL 关系型数据库 分布式数据库
PolarDB产品使用问题之一般都分多少个分区
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
5月前
|
存储 关系型数据库 分布式数据库
PolarDB产品使用问题之如何变更存储配置
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
5月前
|
关系型数据库 MySQL 分布式数据库
PolarDB产品使用问题之如何对集群变更配置
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。

相关产品

  • 云原生分布式数据库 PolarDB-X