程序员

PolarDB-X 让“Online DDL”更Online

作者:admin 2021-04-05 我要评论

作者 梦实 数据库的用户对数据库都有一个很简单的要求 “我能不能随时随地做DDL 不要让我守到半夜再搞了。” 为了这个目标 各种各样的数据库采用了不同的方法来...

作者 梦实



数据库的用户对数据库都有一个很简单的要求


“我能不能随时随地做DDL 不要让我守到半夜再搞了。”


为了这个目标 各种各样的数据库采用了不同的方法来优化DDL这件事 MySQL也从5.6开始逐渐支持“Online DDL”。


但问题是 为何已经到了MySQL 8.0的时代 你能看到的各种MySQL最佳实践\开发规范里 依然建议把DDL放在业务低峰期来做呢。PolarDB-X对此作了很多优化 期望让用户做DDL的时候能更任性。


我们得先看一下 MySQL的DDL 为什么不那么“Online”。




MySQL中的MDL 元数据锁


MySQL中有个MDL 它会保证在DDL变更过程中 所有的事务都在使用同一份元数据。


例如 我们对一个表做一个加列的操作 ALTER TABLE t1 ADD COLUMN(c1 int) MDL确保正在运行的事务 要么全部能看到c1列 要么全部看不到c1列。实际上 MDL起到了元数据切换过程中 排空已有事务的效果。在MySQL中 DDL/DML/DQL等操作 都会对元数据加锁。


MDL会带来一些问题 我们看下面的例子


时间点0 我们在连接1中 对t1表做一个INSERT操作 但是不要提交这个事务

1.png


时间点1 我们在连接2中 对t1表做一个添加索引的DDL操作 这个DDL操作会阻塞住

2.png


时间点2 我们在连接3中 对t1表做一个SELECT操作 会发现 这个只读操作也会阻塞住

3.png


时间点3 提交连接1的事务

4.png


连接2的DDL操作立即返回结果

5.png


连接3的SELECT操作立即返回结果

6.png

image.gif


这个就很奇怪了 一般我们都以为

只读操作不会被写操作阻塞 为什么SELECT语句都会阻塞
MySQL的创建索引操作 特指例子里这个很常见的DDL 不是ONLINE的吗 为什么会阻塞我的业务


以上现象的原因就在于MDL锁上

连接1的INSERT对t1的元数据加了读锁
连接2的DDL获取t1的排它锁 连接2会被连接1阻塞 同时锁住后续的所有读请求
连接3的SELECT获取t1的读锁 被连接2阻塞住。


从上面的现象看 MDL锁带来了如下的问题

如果DDL执行之前有长事务 那会阻塞后续这个表上的所有请求 无论读写 进一步占用MySQL的线程资源 甚至引发雪崩 导致其他表的访问也出现问题
MySQL虽然有ONLINE DDL 这个ONLINE更多体现在回填数据阶段。DDL依旧只能在业务低峰期来使用 没有达到真正ONLINE 完全不阻塞业务请求 的目的。


这个事是很坑的 我们需要的是真正的ONLINE DDL能力。




元数据的版本


这里要先解释一个概念 什么是一个元数据的版本


有一个误区是 一个DDL操作 比如上述的加索引的操作 并不是只有“有索引”“没索引”两个版本 而是分成了多个版本。


例如PolarDB-X中的CREATE INDEX操作 整个过程会涉及ABSENT(vn) DELETE_ONLY(vn 1) WRITE_ONLY(vn 2) PUBLISH(vn 3)多次版本切换。


对于MySQL来说 也有类似的概念 即在MySQL中 一次DDL操作可能会需要多次获取MDL的操作 这也加剧了MySQL DDL过程中MDL的争抢。




双版本元数据


为了解决MDL的问题 让DDL能够做到真正的ONLINE PolarDB-X使用双版本元数据来解决这个问题。


所谓多版本元数据指的是 PolarDB-X集群中 允许最多同时存在两个版本的元数据 vn与vn 1 每个事务使用的元数据版本由其事务开始时候的元数据版本为准。当使用低版本元数据的事务全部结束之后 低版本的元数据会被清理掉。


7.png

8.png



我们在PolarDB-X上重复上面的例子 会得到这样的结果 DDL不会再因为长事务阻塞所有的操作


时间点0 我们在连接1中 对t1表做一个INSERT操作 但是不要提交这个事务。同时我们可以看到 此时看到的t1的版本是v1

9.png


时间点1 我们在连接2中 对t1表做一个添加索引的DDL操作 这个DDL操作会在v1切换到v2过程中被阻塞住 因为它会尝试获取t1:v1的元数据锁

10.png


时间点2 我们在连接3中 对t1表做一个SELECT操作 这个操作会立即返回 不会阻塞。同时我们看到 这个连接看到的t1的版本是v2

11.png


我们在连接1中 查看t1的元数据版本依旧是v1。此时我们就能看出 DDL前后的两个事务 使用了不同版本的元数据

12.png


时间点3 提交连接1的事务

13.png


连接2的DDL操作立即返回结果

14.png


3个连接看到的t1的元数据的版本都变成了v5 思考下 为什么是v5

15.png




小结


PolarDB-X相对于MySQL 彻底解决了MDL锁的问题 Online DDL的元数据切换做到了非常平滑的切换 不会因为长事务阻塞元数据切换 进一步造成更大范围的阻塞 是一种比MySQL的Online DDL更Online的实现。


除了更Online PolarDB-X还为DDL的性能、开销等都做了很多的优化 欢迎持续关注我们的文章。



【相关阅读】

PolarDB-X SQL限流 为您的核心业务保驾护航

通篇干货 纵观 PolarDB-X 并行计算框架

HTAP 数据库“必修课” PolarDB-X Online Schema Change

PolarDB-X 向量化引擎的类型绑定与代码生成

每次都需要解释大量指令 使用 PolarDB-X 向量化引擎

PolarDB-X 面向 HTAP 的混合执行器

PolarDB-X 面向 HTAP 的 CBO 优化器

如宝马3系和5系 PolarDB-X 与 DRDS 并驾齐驱

PolarDB-X 存储架构之“基于Paxos的最佳生产实践”

PolarDB-X 私有协议 提升集群的性能和稳定性

技术解读 | PolarDB-X 分布式事务的实现

技术解读 | PolarDB-X 强一致分布式事务

PolarDB-X 一致性共识协议 (X-Paxos)


本文转自网络,原文链接:https://developer.aliyun.com/article/783280

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 详解git基本操作和指令

    详解git基本操作和指令

  • 详解idea中Git的Stash Changes和UnStas

    详解idea中Git的Stash Changes和UnStas

  • 详解Visual Studio使用Git忽略不想上传

    详解Visual Studio使用Git忽略不想上传

  • Git 如何放弃所有本地修改的方法

    Git 如何放弃所有本地修改的方法

腾讯云代理商
海外云服务器