如何在 PolarDB - X 中进行 Online DDL|学习笔记(三)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云原生数据库 PolarDB 分布式版,标准版 2核8GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 快速学习如何在 PolarDB - X 中进行 Online DDL

开发者学堂课程【如何在PolarDB-X中进行Online DDL如何在 PolarDB - X 中进行 Online DDL】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/986/detail/14929


如何在 PolarDB - X 中进行 Online DDL

三、PolarDB - X online DDL 的原理

1. mySQL online DDL 基本原理

image.png在了解这个之前,先看一下mySQL数据库,也就是单机数据库是怎么做的,以加索引这样一个ddl为例,还要看一下mySQL做一个online ddl的过程,mySQL做ddl分为三个步骤,初始化执行,最后完成数据的更新这样三个步骤。

加索引是在第一步会获取目标表上的MDL,也就是共享的锁,之后会进入一个执行的阶段,执行阶段首先会获取互斥的一个表,拿到这个锁之后,其他的 DDL,md l都不能再访问这张表的原数据,拿到这个锁之后,他会等待因为这个MDL要等前面的比如还有一些未完成的事务,这个时候他要等那些事务结束,才能够获取到这个互斥的md l的锁,其实就是等待之前使用旧版本的原数据的所有事物都结束这样一个机制,等完之后拿到这个锁就开始准备中间的一些内部的数据结构,这边叫做rowlog,可以简单的理解为记录索引的数据的变更的这样的数据结构,这些准备工作做完之后,把锁再次降低,降低之后,后续的dml就可以访问这张表的原数据了,拿到的还是与原来数据一样的结构,也就是在这个阶段会拿一个互斥锁,这个锁会等待之前所有的事物结束,同时会阻塞后面的DML,这是一个点,等他开始构建索引就是拷贝数据执行完包括把存量的数据复制到索引表以及把rowlog里面的增量数据全部应用到这张索引表,之后有一部应用,最后一块rowlog,这个时候他要再次进行一次加锁,这样的一个过程,同时禁止这张表里面相关的写入,也就是会达到一个这样的效果,最后一块rowlog里面的增量写入了,他把这部分数据在应用的索引表,应用完以后可以看成索引表里面的数据与原表的数据完全的一致了,之后再次释放这样一个锁,释放完成之后,完成了数据的更新,在这个过程中可以看到mySQL online DDL里面有三个地方加了一个md l互斥锁,加的过程会对业务有一些影响,所以即使每次mySQL online 有了DDL这个能力,通常在业务做运维时,如果对mySQL online做ddl操作时需要在业务的低峰期进行。

2.F1 online schema change  基本原理

image.png来看一下PolarDB - X 里面是怎样做这件事情的,PolarDB - X 是一个分布式系统,怎么不是系统相对于单机来说引入了新的复杂度,目前业界比较主流的一种在分布式系统里面实现schema变更的方案是.F1 online schema change这样一个方案,他解决的问题是,如果你的原信息从老版本直接切换到新版本就像单机里面那样操作的话,会引入一些新的问题,这个就是为了解决这些问题的,一两个例子来看一下都有哪些问题,首先来看这张图最上面的左面,这是第一个问题,他的问题就是如果将数据直接从老版本切换到新版本会有什么问题,老版本是没有索引的,还是讲创建索引这样一个场景,如果老版本的schema里面这张表的这个列是没有索引的,在新的版本中加了索引,因为是一个分布式的系统,所以会有多个cn的节点,比如这张图里面会有两个cn的节点,这两个cn的节点没有办法同时进行原数据的生效,就会存在一段时间在cn0里面已经拿到了最新版本的原数据,他已经知道了这张索引表的存在,在老的cn1里面他还是拿到老版本的schema,这是他依然认为这张表是没有索引的,这个时候比如在业务上面来了两个请求,在cn1上是insert的请求是先到的,Cn1就会根据新版本的schema信息认为有索引,他会同时的往主表索引表插入两条数据来保证数据的一致性,这个时候cn1上面就收到了另外一条delete语句,他删除的刚好是前面的Cn 0的insert那条语句插入的数据,因为cn1上拿的还是老版本的schema信息,所以他并不知道索引表的存在,就只是把主表上的这条数据进行删除,这样就会导致索引表里面多出了一条数据,他在主表里面是找不到原来的数据的,这就是第一个问题。

第二个问题就是上面这张图的右边,还是一个类似的场景,如果cn1收到的是一个insert语句,因为上面还是一个老版本的schema信息,他不知道索引表,所以他只向主表去插入一条记录,这就会导致索引表相对于主表少了一条数据,这样两边还是有不一致的问题,这就是如果我们将老版本schema与新版本的schema之间直接切换引入的众多问题当中的其中两个问题。

在 online schema change这个论文里面,为了解决这个问题,引入了两个阶段,就是从索引不存在到索引存在这中间又加入了两个新的状态,叫做delete only,write only这样的两个状态,原来直接从不存在到存在切换会引入问题,那么经过严格的证明从不存在到delete only到write only再到可见也就是public这个过程就保证了不会出现这个问题,再来看一下是如何避免这个问题的。针对于刚才所讲的问题一,来看上面这张图的左边,还是刚才的场景,Cn 0和cn1拿到了不同版本的schema的信息,这个时候cn零就收到了一个insert语句,他拿到的是新版本的schema信息,此时因为拿到新版本对索引的描述是delete only,也就是不能向里面insert数据,Delete only本身就是这样的,所以cn 0拿到这样的insert语句之后指望主表去insert表数据,没有向索引表insert一条数据,那么这个时候如果cn1里面收到了delete语句,因为他拿的是老版本,他认为只有一个主表的存在,索引表此时还没存在,他就对主表里面的数据进行删除,这个时候大家发现最终主表和索引表里面的数据是一致的,也就是规避了第一个问题。

再来看一下是如何回避第二个问题的,例如现在的cn 0和cn 之间的schema信息都往前迭代,cn0已经到了delete only版本,C N1还是在上一个版本,此时cn 1收到了一条insert语句,那么按照delete only的约束是不能往索引表insert的数据的虽然他知道索引表存在,但是它不能向里面写数据,依然只向主表去写了一份数据,这个时候看上去索引表是少一个条数据的,但是没关系,再接下来的从whiteonly变成public这一步中间还有一个数据回填的过程,所谓的数据回填就是将图标里面的数据陈亮的复制到索引表的一个过程,在复制的过程当中,因为刚才cn1 insert里面的那条数据已经在主表存在了,所以在回填的过程中会将这条数据复制到索引表,也就解决了刚才所说的问题二,这就是论文的大概过程,同时他还会有一些其他问题,里面都会有一个详细的论述。

简单来说就是这篇论文解决了一个问题,在分布式的系统当中原数据怎么从老版本变成一个新的版本,在变化的过程当中对业务是没有影响,对数据也是保持能够一致的,能够保证一个这样的效果。

3.PolarDB - X online DDL 的基本流程

image.pngPolarDB - X 是基于那篇论文的一个思想来做原数据版本的变更,但是在他的基础之上做了一些优化,来时online的效果更online,就是没有阻塞业务的点,第二个是有些机制在保证,如果在执行DDL过程当中系统上任何节点挂了这个DDL本身是能够恢复的,也就是ddl也保证了ccID,首先来看一下在PolarDB - X 里面用户提交了一个ddl大概的处理流程,首先在这张图的最左边用户提交了一个ddl,他可能提交给了一个节点,这个节点就会把ddl这个任务写到gms,就是前面讲到的原数据中心里面,写成一个ddl任务,这些cn当中会有一个主节点,主节点查到这个任务之后会分派,最终把这个任务分配给系统当中能够执行这个ddl worker的节点,worker节点就会做与原数据相关的一些变更,比如先把dn版本里面的一些信息schema进行改变,现在dn里面也做一些相应的修改,做完之后会把gms里面的数据做一个更新,在这个过程当中他就会因为原数据变更的过程是一个阶段性的,比如从刚才的delete only到write only再到public会涉及到几次原数据版本的切换,每次结婚都会用到刚才所说的online schema change那样的流程来进行变更,这个工作全部是在ddl worker中进行的,例如在这里从初始的状态切换到delete only的时候,这个ddl worker中间有一部就是做完gms相关数据变更之后就会开始通知所有的其他的cn,现在的元素就已经从原来的状态变为了delete only状态,开始通知到所有cn的节点,这些cn节点都会在一段时间之后获取到最新的schema信息,等所有的cn节点都已经加载到了新版本之后,就开始切换到下一个状态,也就是delete only这个过程也类似,直到最后完成索引的添加,这个过程在上节课简单的提到过。涉及到这个过程里面具体的一部分,比如说具体怎么原数据完成变更之后怎么通知到所有cn节点让他们完成加载的。

image.png

首先还是以创建索引ddl,发起了创建ddl这样的一个操作,ddl worker节点也完成了相关的索引表以及原数据表的更新,之后开始通知所有的节点加载到新的schema信息,比如现在node 0 worker会通知到Node1,Node收到通知新版本加载之后,会首先检查本地上面的信息是不是已经让加载的信息更新了或者跟他一样,如果大于等于这个版本他可以忽略这个通知,如果不是比他旧就继续往下走这个流程,继续往下走,这里有部分流程应该是写错了,再往下首先应该去gms加载到原数据最新信息,加载完成之后就完成了节点里面缓存的schema信息,同时在这个节点上还运行着其他一些事务,这些事物里面可能用的还是版版本的schema,所以他要等那些用老版本信息的事物全部执行完成之后,才告诉worker节点已经彻底完成了schema的切换,这个时候他用了一种机制,PolarDB - X自己设计的机制叫mdl加索引这个机制,他会去尝试获取这个节点上面的老版本schema信息的mdl的一个锁,这个锁是一个排他锁,如果有事物持有了老版本的共享锁这个排他锁就会阻止,直到把前面的所有事务完成,一旦在这里面获取到这个锁,就意味着使用老版本的那些事物已经执行完成了,这个时候就通知到worker节点,Note1已经完成了新版本数据的加载,这个简单来说就是通知所有的节点加载原数据的一个过程,但是真实的逻辑要比这个复杂,比如要处理一个节点,没有响应怎么办这样的问题,如果ddl本身挂了怎么恢复,一系列非常复杂的过程,如果对这个过程感兴趣,可以去看一下代码。

总结一下PolarDB - X online DDL就是会有这样几个特点

第一个是不会对事物执行引入额外开销,这样保证系统的一个效率。

第二个是在没有异常节点的情况下,就是没有cn没有响应或者是挂了没有这样异常的情况下,schema版本变更不影响事务执行,并且通常没有数据回填的ddl操作毫秒级完成,果存在异常节点,系统仅仅阻止异常节点上的事务提交,其他节点不受影响,无数据回填的ddl操作分钟完成,MDL锁不阻塞后续DML这个与前面mySQL的dml是不一样的,mySQL加dml互斥锁会影响后续dml操作,处于等待的状态,在PolarDB - X 里面经过设计之后是不会阻塞的。

同时支持分布式md l死锁检测,同时很重要的一点是PolarDB - X 里面有acid这样一个事务保障。

相关实践学习
快速体验PolarDB开源数据库
本实验环境已内置PostgreSQL数据库以及PolarDB开源数据库:PolarDB PostgreSQL版和PolarDB分布式版,支持一键拉起使用,方便各位开发者学习使用。
相关文章
|
SQL 关系型数据库 测试技术
如何在PolarDB-X中进行Online DDL
《PolarDB-X 动手实践》系列第五期,本场景带您体验如何在PolarDB-X中进行Online DDL。
|
SQL 运维 关系型数据库
PolarDB-X源码解读:DDL的一生(下)
在《DDL的一生(上)》中,我们以添加全局二级索引为例,从DDL开发者的视角介绍了如何在DDL引擎框架下实现一个逻辑DDL。在本篇,作者将从DDL引擎的视角出发,向读者介绍DDL引擎的架构、实现,以及DDL引擎与DDL Job的交互逻辑。
PolarDB-X源码解读:DDL的一生(下)
|
SQL 缓存 Java
开源分布式数据库PolarDB-X源码解读——PolarDB-X源码解读(九):DDL的一生(上)
开源分布式数据库PolarDB-X源码解读——PolarDB-X源码解读(九):DDL的一生(上)
282 0
|
SQL 运维 关系型数据库
开源分布式数据库PolarDB-X源码解读——PolarDB-X源码解读(十):DDL的一生(下)
开源分布式数据库PolarDB-X源码解读——PolarDB-X源码解读(十):DDL的一生(下)
210 0
|
SQL 关系型数据库 MySQL
实践教程之如何在PolarDB-X中进行Online DDL
PolarDB-X 为了方便用户体验,提供了免费的实验环境,您可以在实验环境里体验 PolarDB-X 的安装部署和各种内核特性。除了免费的实验,PolarDB-X 也提供免费的视频课程,手把手教你玩转 PolarDB-X 分布式数据库。
实践教程之如何在PolarDB-X中进行Online DDL
|
8月前
|
SQL 关系型数据库 测试技术
实践教程之在PolarDB-X中进行Online DDL
PolarDB-X 为了方便用户体验,提供了免费的实验环境,您可以在实验环境里体验 PolarDB-X 的安装部署和各种内核特性。除了免费的实验,PolarDB-X 也提供免费的视频课程,手把手教你玩转 PolarDB-X 分布式数据库。
实践教程之在PolarDB-X中进行Online DDL
|
SQL 弹性计算 监控
如何在 PolarDB - X 中进行 Online DDL|学习笔记(一)
快速学习如何在 PolarDB - X 中进行 Online DDL
如何在 PolarDB - X 中进行 Online DDL|学习笔记(一)
|
SQL 存储 运维
PolarDB-X DDL也要追求ACID?
纵观数据库领域数十年来的发展,关系型数据库脱颖而出的一个重要原因是,它支持用户灵活地定义和修改“数据模型”。 模型演进(schema evolution)是其中的关键问题,在SQL-92标准中提出了一系列用于描述关系模型的语法,也就是各种DDL语句。DDL通常也是各个数据库厂商夹带私货最多的地方,各家数据库都会推出很多自己独有的DDL语法,以支持更灵活的模型演进。 本文着眼于DDL的ACID特性,讨论PolarDB-X如何面对以及解决这些问题。
428 1
|
SQL 缓存 Java
PolarDB-X源码解读系列:DDL的一生(上)
本文主要解读了 PolarDB-X 中 CN 端的DDL Job定义相关的代码,以添加全局二级索引为例,对DDL Job定义和执行的整体流程进行了梳理,并着重阐述了DDL job定义中涉及online和crash safe特性的关键逻辑。
|
SQL 缓存 Java
PolarDB-X 源码解读:DDL的一生(上)
一条SQL语句进入PolarDB-X的CN后,将经历协议层、优化器、执行器的完整处理流程。首先经过解析、鉴权、校验,被解析为关系代数树后,在优化器中经历RBO和CBO生成执行计划,最终在DN上执行完成。与DML不同的是,逻辑DDL语句还涉及对元数据的读写和物理DDL,直接影响系统状态一致性。
PolarDB-X 源码解读:DDL的一生(上)