我定期需要对表(tables)进行更改……主要是添加列(columns)。
这种更改其实只是简单的`alter table`操作……
但是我这张表目前有4000万行数据,而且他们正在快速地增长……
所以这种情况下`alter table`操作将会花费数小时时间,
因为我使用的是亚马逊RDS[sic],
我没有办法部署我地从服务器,因而也没有办法改善主服务器。
所以我的问题是,是否有办法在停机时间最小化的情况下做到这一点呢?
我不介意一个小时或甚至几天的操作,如果用户仍然可以使用DB…
(译者:如何在不停机的情况下修改表结构及数据)

—— Stack Overflow serverfault 1

上面的问题在2010年发布,但是关于模式改变的停顿的焦虑仍然存在。

当我们在设计CockroachDB的模式改变引擎(schema change engine)的时候,我们希望更好地构建它。

我们希望提供一种更新表模式(只需运行alter table命令)的简单方法,而不必让应用程序遭受任何负面后果——包括停机时间。

我们希望模式更改是CockroachDB的内置特性,不需要额外的工具、资源或操作的自组织排序;

并且所有这些,对应用程序的读/写延迟没有影响。

在这篇文章中,我将解释我们的在线模式改变策略。

我将讨论如何管理对架构元素(如列和索引)的更改,而不必强制停机。

这就是我们所做的

模式更改涉及更新模式以及添加或删除与该更改相关联的表数据。

两个基本的分布式数据库特性使得这一点特别棘手:

  1. 高性能:为了优化数据库性能,必须采用跨数据库节点缓存架构。保持分布式缓存一致性是有挑战性的。
  2. 大表:数据库中的表可以非常大。与模式改变相关联的回填或清除表数据需要时间,并且正确地执行,而与此同时,不禁用对数据库的访问是具有挑战性的。

我们用于 维护一致的分布式模式缓存以及一致表数据 拥抱着 同时发生的模式的多个版本,我们可以在使用旧模式的同时推出我们的新的模式。

(译者的理解:他可能是先继续维护旧的模式,然后新建一个新的模式,然后再一步步地往新的模式里面填旧的模式里面的数据,当然这个时候新的模式里面的数据也会变动,反正就是一点一点的往旧的模式靠,等到某一个时间点和旧的模式保持同步了,好!立马抛弃旧的模式,启用新的模式。)

它在不持有锁的情况下回填(或删除)基础表数据。

这个解决方案是由谷歌F1团队所做的工作得出的。

安全模式展开(Safe schema rollout)

一个schema元素(它可以是索引或列,虽然在这篇文章的其余部分,我们将重点放在索引的情况下),有相关的数据,这些数据可以被SQL DML命令删除、写入或读取(例如,插入INSERT、更新UPDATE、删除DELETE、选择SELECT)。

CockroachDB采用的策略是首次展现(rollout)一个新的索引,包括对这些DML命令进行删除、写入和读取功能,一个接一个地以分级的方式,而不是同时进行。

添加一个新的索引遵循如下所述的离散阶段:

  1. 授予删除(DELETE)功能。
  2. 授予写入(WRITE)功能。
  3. 回填索引数据。
  4. 授予读取(READ)功能。

在新版本的架构中,一个能力与所有先前授予的能力一起被授予。

为了正确起见,只有在整个集群使用包含所有先前授予的能力的架构之后,才可以授予新的能力。

因此,该过程在每个阶段之前暂停,允许先前授予的功能在下一个功能可以被授予之前传播到整个集群。

删除索引按照相反的方向进行:

  1. 撤销读取(READ)功能。
  2. 撤销写入(WRITE)功能。
  3. 清除索引数据。
  4. 撤销删除(DELETE)功能。

类似地,只有在前一个功能在整个群集上的撤销传播完之后才撤销当前的功能。

删除能力(Delete capability):避免虚假索引条目

通过将索引置于 DELETE_ONLY 状态,来赋予这种功能。

拥有这种能力,SQL DML命令限制了他们自己:

  • 删除(DELETE)是完全有效的删除行连同基础索引数据。
  • 更新(UPDATE)删除旧索引条目,但限制自身不写入新的条目。
  • 插入(INSERT)和选择(SELECT)忽略索引。

在下一阶段授予索引的写入能力的节点可以信任整个集群使用索引的删除能力。

因此,当它接收到插入命令并插入一个行的索引条目时,另一个只有删除能力的节点在看到同一行的删除命令时,将正确删除行的索引条目。

该索引将避免因悬空索引条目而中毒。

当模式改变丢弃索引时,仅在成功地将写入能力撤回群集之后清除关联索引数据;

整个集群只有删除能力,允许安全清除。

写入(Write capability)能力:避免丢失索引条目

这种能力是通过将索引放置在 WRITE_AND_DELETE_ONLY 状态,授予删除和写入能力来实现的。

  • 插入(INSERT)、更新(UPDATE)和删除(DELETE)命令正常运行,根据需要添加或删除索引项。
  • 另一方面,选择(SELECT)需要读取能力,而忽略索引。

索引回填仅在整个群集能够写入之后才运行。

在回填过程中,在任何节点上接收的插入命令创建具有合法索引项的新行,并且不依赖于单独的回填过程来创建行的索引条目。

回填完成后,将不会有缺失的索引条目。

读取能力(Read capability)

这最后一个能力是通过使索引激活而授予的,并通过所有命令打开索引的完整使用。

快速模式展开(Fast schema rollout)

在模式更改过程的每个阶段之间,允许整个集群收敛到表模式的最新版本。

一个简单的模式缓存机制可能会使用5分钟的TTL,但是这会迫使模式改变过程等待许多分钟,然后才相信最新的版本是唯一的一个具有活跃状态的和完全授予/撤销的能力的版本。

在 CockroachDB 中,我们在模式版本上开发了租约(leases),以加快集群收敛到最新的模式版本,这又加速了模式改变过程。

在使用SQL DML命令的表模式之前,运行该命令的节点自一段重要的时间内获得该模式的读取租约(以分钟为单位)。

当更新的表架构版本变为活动时,它将在整个集群上广播,向新版本通知节点并使它们主动释放旧版本上的租约。

如果某些节点不健康并且不主动释放它们的租约,则 rollout 将等待租约过期,并将被延迟。

我们通过遵循以下两条规则来让模式更改策略变得简单:

  • 新租约只授予最新的模式版本。
  • 有效租约只在两个最新的模式版本上。

有关表租约的更详细讨论,请参见我们在Github仓库上的RFC文档。

可靠的模式展开(Reliable schema rollout)

模式更改由执行模式更改SQL命令的节点引导完成。

由于模式更改操作可能长时间运行,所以当执行它们的节点死亡时,它们需要重新启动。

每个节点运行一个模式转换器 goroutine,它能够运行任何不完整的模式更改。

在执行模式更改之前,模式更改器 goroutine 首先获取表上的独占写入租约,使其成为唯一指导模式更改的许可。

总结

在 CockroachDB 中,在线模式更改使用起来是很简单的,模式更改展开的处理也是方便、快速和可靠的。

改变是不可避免的,现在是你不必担心的时候了!

我们要感谢来自谷歌F1团队的人们发布 在线模式更改 的类似实现,从中我们获得了很多灵感。


Apptree. Stack Overflow. “Modifying columns of a very large mysql table with little or no downtime.” August 26, 2010.

CockroachDB学习笔记——[译]在CockroachDB中如何让在线模式更改成为可能的更多相关文章

  1. CockroachDB学习笔记——[译]CockroachDB中的SQL:映射表中数据到键值存储

    CockroachDB学习笔记--[译]CockroachDB中的SQL:映射表中数据到键值存储 原文标题:SQL in CockroachDB: Mapping Table Data to Key- ...

  2. CockroachDB学习笔记——[译]如何优化Go语言中的垃圾回收

    原文链接:https://www.cockroachlabs.com/blog/how-to-optimize-garbage-collection-in-go/ 原作者:Jessica Edward ...

  3. CockroachDB学习笔记——[译]Cgo的成本与复杂性

    原文链接:https://www.cockroachlabs.com/blog/the-cost-and-complexity-of-cgo/ 原作者:Tobias Schottdorf 原文日期:D ...

  4. CockroachDB学习笔记——[译]为什么Go语言是CockroachDB的正确选择

    原文链接:https://www.cockroachlabs.com/blog/why-go-was-the-right-choice-for-cockroachdb/ 原作者:Jessica Edw ...

  5. CockroachDB学习笔记——[译]The New Stack:遇见CockroachDB,一个弹性SQL数据库

    原文链接:https://www.cockroachlabs.com/blog/the-new-stack-meet-cockroachdb-the-resilient-sql-database/ 原 ...

  6. CockroachDB学习笔记——[译]CockroachDB是如何进行分布式原子事务的

    原文:How CockroachDB Does Distributed, Atomic Transactions 原文链接:https://www.cockroachlabs.com/blog/how ...

  7. CockroachDB学习笔记——[译]Scaling Raft

    原文链接:https://www.cockroachlabs.com/blog/scaling-raft/ 原作者:Ben Darnell 原文日期:Jun 11, 2015 译:zifeiy 在Co ...

  8. CockroachDB学习笔记——[译]Hello World

    原文链接:https://www.cockroachlabs.com/blog/hello-world/ 原作者:Spencer Kimball 原文日期:Jun 4, 2015 译:zifeiy 数 ...

  9. CockroachDB学习笔记——对此的选择

    无意间了解到TiDB,然后知道了他是一款国产团队开源的NewSQL数据库, 看了一下官网,有很多中文的文档和技术分享挺不错的. 但是安装起来好像挺麻烦的说. 测试的硬件环境 也吓死我了,我只有一台笔记 ...

随机推荐

  1. Nginx中ngx_http_auth_basic_moudel和ngx_http_stub_status_module模块

    ngx_http_auth_basic_module实现基于⽤用户的访问控制,使⽤用basic机制进⾏行行⽤用户认证指令:5.1 auth_basicSyntax: auth_basic string ...

  2. BackGroundWorker组件使用、Winform控件的Invoke安全调用

    BackgroundWorker是·net里用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作. 可以通过编程方式创建 BackgroundWorker,也可以将它从"工具 ...

  3. [Javascript] Create an Image with JavaScript Using Fetch and URL.createObjectURL

    Most developers are familiar with using img tags and assigning the src inside of HTML. It is also po ...

  4. P1578 奶牛浴场 有障碍点的最大子矩形

    这题咕咕了很久终于写了\(QwQ\) 思路:扫? 提交:2次 错因:数据差评,第一次把矩形的长宽搞反了竟然只有一个点没有\(A\). 题解: 显然能成为答案的矩形的边界一定有障碍点或者与大矩形边界重合 ...

  5. 浏览器事件环(EventLoop)

    1. 基础知识 1. js语言特点 1. js语言是单线程语言,主线程是单线程.如UI渲染,脚本加载是主线程任务. 2. js语言采用事件循环(EventLoop)机制. 2. 同步任务: 不被引擎挂 ...

  6. 基本react-native模板

    import React, { Component } from 'react'; import { Text } from 'react-native'; export default class ...

  7. 富文本编辑器word

    tinymce是很优秀的一款富文本编辑器,可以去官网下载.https://www.tiny.cloud 这里分享的是它官网的一个收费插件powerpaste的旧版本源码,但也不影响功能使用. http ...

  8. 删数问题(SDUT2072 )

    删数问题 Time Limit: 1000 msMemory Limit: 65536 KiB Problem Description 键盘输入一个高精度的正整数n(≤100位),去掉其中任意s个数字 ...

  9. iOS Jenkins 自动化打包构建

    前言 在测试app项目过程中,通常都是需要开发打测试包给到测试,但是无论是iOS还是Android的打包过程都是相当漫长的,频繁的回归测试需要频繁的打包,对于开发同学影响还是蛮大的.因此在这种情况下, ...

  10. hdu6736(寻找最小环)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6736 题意: 在给定图中寻找所有最小环 保证不存在一条边经过两个简单环 数据范围: $1\leq n ...