第6章-2 schema管理

        上一篇:《第6章-1 数据类型》,接着讲schema管理

schema管理

        修改schema是数据库工程师必须承担的最常见任务之一。当达到运行数十个或数百个数据库实例的阶段,而这些实例又具有不同的业务场景和不断变化的功能时,需要注意,不要让修改schema成为整个组织的瓶颈,而是仍然可以安全地进行且不会中断操作。本节将介绍如何将schema变更管理视为“数据存储平台”的一部分,该战略应该以什么核心价值观为指导,可以引入什么工具来实现该战略,以及如何将其整合到更大的软件交付生命周期中。

作为数据存储平台一部分的schema管理

        如果你与一个快速发展的组织中的任何一位工程主管交谈,你会发现工程师的效率和从功能设计到投入生产的时间是他们最需要优化的事情。在这种情况下,在计划大规模管理schema时,你的任务是不允许schema管理成为一个手动过程,从而因为一个或几个人阻碍整个工程组织的进度。

建立合作伙伴团队以获得成功

        随着组织中依赖MySQL实例的团队数量的增长,你希望始终成为这些团队成功的赋能者,而不是他们完成工作所需要通过的难关。这也适用于schema修改,这意味着你希望创建一个不依赖于“仅由数据库团队执行”的部署schema修改的路径。

将schema管理与持续集成相整合

        在介绍完一些支持大规模schema管理的工具之后,我们将讨论如何将它们与CI管道集成。但现在我们想强调的是,如果你从schema修改将由功能开发团队而不仅仅是数据库团队管理的前提开始,那么你需要尽可能地接近工作流,以了解这些团队如何部署代码更改。科学已经证明https://oreil.ly/hozRf),以对待代码部署的方式对待schema管理的团队会经历一个更积极的功能交付过程,并看到团队效率的提升。我们将在考虑软件交付实践的情况下讨论支持该迭代的工具。

schema修改的源代码控制

        我们部署的代码都会使用源代码控制,对吗?那么为什么不考虑数据库的schema应该是什么样子的呢?大规模schema管理的第一步是确保源代码管理支持并跟踪所做的更改。这不仅是一件值得做的好事,在很多情况下,这是友好的合规团队所要求的,如第13章所示。

        让我们介绍一些能够在数据库schema上进行迭代的工具。

        为了使你的组织获得最大的价值,请使用与代码部署相同的CI工具。

        付费方案。在过去的几年中,数据库schema管理作为一种企业工具的前景急剧增长,特别是增加了对MySQL安装的支持之后。如果你正在寻找一个现成的解决方案来帮助组织管理schema更改,如下是一些应该考虑的事情。

成本

        成本模型各不相同,所以如果你选择的解决方案是按目标(要管理的schema)收费,那么应该小心,因为成本可能会很快累加到非常高。

在线schema管理

        在撰写本文时,Flyway等付费解决方案(参见链接25 https://flywaydb.org/)没有一条清晰的路径来以非阻塞的方式为你运行schema更改,尽管它的竞争对手Liquibase正在推出(参见链接26 Liquibase Community)一个支持ercona的在线schema更改的插件。你需要了解每个供应商代替你做出的权衡,以及这些权衡对可用性意味着什么,尤其是如果你计划使用这些供应商来管理大型数据库(磁盘上有多TB)的schema更改。

开箱即用的集成

        这些工具中的大多数都假设了你的内部软件是用什么语言编写的,因此提供了对应的挂钩接口(Hook)来与现有软件交付过程相集成。如果你的应用由多种语言编写,或者正在改变主要的软件语言,这可能会将其中一些供应商排除在外。在下一节中,我们将介绍在实现schema的源代码管理时,如果需要“自己动手”该怎么做。

        开源方案。如果购买付费工具遥不可及,或者如果有正当理由认为当前的解决方案都不适合你的组织,那么可以使用现有的开源工具和组织的CI管道来实现相同的结果。

Skeema(参见链接27 https://www.skeema.io/)是一个在跨多个环境的版本控制中管理schema更改的杰出开源解决方案。Skeema本身不会在生产环境中为你运行schema更改(我们将很快介绍如何做到这一点),但是它是一个很好的工具,可以在每个数据库集群和跨多个环境中跟踪源代码控制存储库中的更改。当与选择的CI解决方案集成时,它的CLI实现提供了很大的灵活性。如何将Skeema直接与CI解决方案集成,需要考虑CI解决方案所具有的功能。这篇由Twilio Sendgrid 团队的这篇博客文章(参见链接28 https://oreil.ly/8YhBS)解释了他们如何将Skeema与Buildkite整合在一起,从而为那些希望管理数据库变更的特性开发团队实现自治。

        请注意,无论此解决方案如何与CI集成,它都需要访问权限才能对所有环境(包括生产环境)运行schema更改。这意味着还需要与安全团队合作,确保创建正确的访问控制,以获得使用持续集成进行自动化schema部署的好处。

        如果你已经在使用Vitess扩展数据库基础设施,那么应该知道Vitess还可以为你管理schema更改。请确保检查文档的相关部分。

建议:

        在过去的几年中,使用自动化和合规性思维方式管理跨环境schema变更的领域得到了显著的发展。在你做出选择时,以下是最后的一些建议:

        ● 尽可能靠近现有的软件部署工具和工作流程。当工程组织变得更大时,你会希望熟悉这一点。

        ● 应该使用能够集成针对schema更改的基本检测的工具,以确保满足一些基线需求。如果新表没有使用正确的字符集,或者有已决定不允许使用的外键,那么你的解决方案应该自动使代码合并请求失败。

        ● 如果所在的组织使用多种编程语言且发展迅速,请确保不会意外地引入人为瓶颈,例如,将所有数据库和所有schema更改都放在一个代码存储库中。记住,这里的目标是工程团队的效率。

在生产环境中运行schema更改

        我们已经讨论了跟踪和管理组织部署schema更改的选项,接下来讨论如何在不影响数据库或依赖它们的服务的正常运行时间的情况下在生产环境中运行这些更改。

        原生DDL语句。MySQL在5.6版中引入了非阻塞的schema更改,但在这个大版本中,该特性附带了一些警告,使得仅限于非常特定的schema更改类型才能使用。

        当8.0版本正式发布时,MySQL对原生DDL的支持得到了极大的扩展,尽管仍然不是通用的。对主键的更改、对字符集的更改、开启每个表的加密以及添加或删除外键,这些都是仍无法通过就地变更(INPLACEalter)的方式进行schema更改的例子。 ( 更多信息请参阅MySQL 文档(参见链接29 https://oreil.ly/nFMKg))我们强烈建议通过文档熟悉使用就地(INPLACE)或即时(INSTANT)算法可以进行哪些更改,这是在MySQL中进行schema更改而不停机的首选原生方法。

        然而,即使需要的更改在8.0及更高版本中已经在技术上有原生DDL的支持,如果要更改的表非常大,而此时如果InnoDB内部保留的记录表更改的日志文件太大,也可能会遇到回滚,导致白费了数小时或数天的工作。你可能需要使用外部工具的另一个原因是,你强烈希望使用节流机制控制表更改的速度。这是可以使用我们将要讨论的外部工具来管理的。

        使用外部工具来运行schema更改。即使你还不能运行具有就地schema更改的所有灵活性的最新和最好的MySQL版本,也仍然可以将CI工具与可用的开源工具结合起来,在不影响服务的情况下自动运行schema更改。实现这一目标的两个主要选择是Percona的pt-online-

        schema-change和GitHub的gh-ost。这两个工具都有文档来学习如何安装和使用,所以我们将集中讨论如何对二者进行选择,你应该考虑的主要优缺点是什么,以及如何提高使用这两种工具作为生产中自动化schema部署管道的安全性。

        需要注意的一点是:任何运行schema更改的外部工具都需要对正在更改的表进行完整的复制。这些工具只会降低更改过程的影响,并且不需要破坏性的写锁,但只有MySQL中的原生DDL可以在没有完整表拷贝的情况下更改表schema。

        pt-online-schema-change的主要吸引力在于它的稳定性以及在MySQL社区中的长期使用。当切换到新的表版本时,它主要利用触发器来为各种规格的表支持schema更改,而对数据库可用性的影响很小。但其核心设计也有权衡。在学习使用pt-online-schema-change来支撑schema部署管道时,请记住以下几点。

pt-online-schema-change

触发器的局限性

        在MySQL 8.0之前,同一个表中不能有多个具有相同操作的触发器。这是什么意思?如果有一个名为sales的表,并且你已经在其上维护一个insert定时触发器,那么MySQL  8.0之前的版本不允许在该表中使用另一个insert触发器。如果试图使用pt-online-schema-change对其运行schema更改,则该工具在尝试添加其运行所需的触发器时将产生错误。尽管我们通常极不鼓励将表触发器作为业务逻辑的一部分使用,但仍然存在遗留选择创建约束的情况,在选择schema更改机制时,这将成为权衡计算的一部分。

触发器对性能的影响

Percona(参见链接30 https://oreil.ly/aGdKk)提供了一些出色的基准测试,展示了在表中定义触发器对性能的影响。大多数情况下这种性能损失可能是无形的,但是如果你恰巧运行的是一个每秒事务吞吐量非常高的数据库实例,那么可能需要更仔细地观察通过pt-online-schema-change引入的触发器的影响,并对其进行更保守的调整以及时中止。

执行并发迁移

        由于在8.0之前的MySQL中使用触发器具有局限性,你会发现不能使用pt-online-schema-change在同一个表中运行多个schema更改。这在一开始可能是一个小麻烦,但如果将该工具集成到一个完整的自动化schema迁移管道中,就可能会成为团队的瓶颈。

外键约束

        尽管该工具对有外键的schema更改提供了一定程度的支持,但仍需要仔细阅读文档,并权衡如何操作才能对数据和事务吞吐量的影响最小。

gh-ost

        gh-ost是由GitHub的数据工程团队创建的,专门作为一种管理schema更改过程的解决方案,既不影响服务,也不使用触发器。它不使用触发器在表复制阶段跟踪更改,而是以副本的形式连接到集群中,并将基于行的复制日志作为更改日志使用。

        在使用gh-ost进行schema更改时,需要仔细考虑的一件事是,现有的数据库是否使用了外键。虽然pt-online-schema-change已经尝试支持外键关系中的父表或子表的schema更改,但这是一个复杂的选择,充满了权衡(是牺牲正常运行时间来保持一致性,还是冒着可能出现不一致的风险)。另外,gh-ost通常会做出选择,如果要更改的表中存在外键,它会完全退出。作为gh-ost的主要贡献者,Shlomi Noach在一篇很长但非常有用的博客文章(参见链接31 The problem with MySQL foreign key constraints in Online Schema Changes – code.openark.org)中解释说,在线schema更改工具终究是工作在数据库引擎之外的,同时使用外键和在线schema更改工具会创建一个难以权衡的环境,他还建议,如果需要在线schema更改,最好完全不要使用外键。

        如果你和团队是这项任务的新手,并且正在为组织中的schema更改的CI铺平道路,只要能够严格遵守不引入外键的原则,那么我们相信gh-ost是更好的解决方案。鉴于其使用的是二进制日志而不是触发跟踪变化,我们认为这是更安全的选择,所以不必担心触发器的性能影响,也不必担心运行的是哪个MySQL版本(甚至能以基于语句的复制模式工作,但会抛出一些警告)。这已经在大规模部署中被证明。

        那么什么时候pt-online-schema-change会是首选项?如果你正在运行许多已存在外键的旧数据库,并且删除外键是很困难的,那么会发现pt-online-schema-change已经尝试对外键提供更广泛的支持,但你必须承担为数据完整性和正常运行时间选择最安全选项的认知负担。此外,gh-ost利用二进制日志来完成其工作,因此如果由于某种原因无法访问这些日志,pt-online-schema-change仍然是一个可行的选项。

        理想的情况是,有一天我们都可以在MySQL中原生进行在线schema更改,但这一天还没有到来。在此之前,开源生态系统在使schema更改成为更容易自动化的过程方面已经走了很长的路。让我们讨论一下如何将所有这些工具组合在一起,形成一个用于schema更改的完整的CI/CD管道。

用于schema更改的CI/CD管道

        至此,我们已经介绍了许多工具,从帮助管理schema定义版本的工具,到在生产中以最短的停机时间进行更改的工具,可以看到,我们已经具备了对schema更改进行全面持续集成和部署的能力,可以消除组织中工程师生产力的巨大瓶颈。让我们把下面列出的这一切放在一起。

对schema源代码控制进行组织

        首先最重要的是,必须在代码存储库中单独分离每个数据库集群的schema定义。如果这里的目标是为不同的团队以不同的速度运行他们的更改提供灵活性,那么将所有数据库的所有schema定义合并到一个代码存储库中是没有意义的。这种分离还允许每个团队在代码存储库中定义不同的代码校验。一些团队可能需要非常特别的字符集和校验集,而其他团队可能可以接受默认设置。对于你的合作伙伴团队来说,灵活性是关键。

        确保记录了特性开发团队的工程师如何从笔记本电脑上的schema更改到在所有环境中运行并在投入生产前运行测试的工作流程。这里的“pull-request”模型非常有用,可以帮助每个团队在更多环境或生产环境中升级和运行更改之前且以自动化的方式定义在请求schema更改时要运行的测试。

安全的基线配置

        为选择的在线schema更改工具定义基线配置。假设你是一个团队,为依赖你提供灵活、可伸缩且安全的解决方案的合作伙伴团队提供工具。当你考虑如何实现在线schema更改工具时,需要分析schema设计的一些考虑因素,它们需要作为测试整体schema更改的代码合并请求的一部分。例如,如果你更喜欢gh-ost的安全性及其无触发器设计,这意味着你必须拥有一个没有外键的数据库平台。不考虑权衡的选择,如果最终决定使用“死亡外键”,那么应该确保在预提交hook或在Skeema代码存储库中测试schema更改的方式中对其进行了编码,这样就可以避免意外地将不希望的schema更改引入生产环境。

        类似地,你应该为在线schema更改工具确定一个基本配置,该工具为更改如何在生产环境中运行提供了一个基本的安全网。在这样的配置中,你可能需要引入的例子包括运行的最大MySQL线程或允许的最大系统负载。当任何一个特性开发团队创建一个新的数据库,并希望用一个代码存储库来跟踪和管理schema更改时,代码存储库模板可以成为一个强大的工具,使正确的事情变得容易。

每个团队的管道灵活性

        在每个数据库的代码存储库中组织schema定义时,为每个拥有该数据库的团队提供了最大的灵活性,以决定如何自动化或人工管理其管道。一个团队可能处于新产品的迭代阶段,只要定义的测试通过,就可以自动升级schema的代码合并请求。另一个团队可能拥有更关键的任务数据库,需要更谨慎的方法,它们倾向于在CI系统将其推进到下一个环境之前,由操作员批准代码合并请求。

        在设计组织如何实现规模化的schema更改部署时,请关注最终目标:为不断增长的工程组织提供速度和安全性,而不让数据库工程团队成为公司在生产中从想法转变为功能的瓶颈。

小结

        好的schema设计是非常普遍的,但是MySQL有特殊的实现细节要考虑。简而言之,让事情尽可能小而简单是一个好主意。MySQL喜欢简单,需要使用数据库的人也喜欢简单。

请记住以下指导原则:

        ● 尽量避免在设计中出现极端情况,例如,强制执行非常复杂的查询或者包含很多列的表设计(很多的意思是介于有点多和非常多之间)。

        ● 使用小的、简单的、适当的数据类型,并避免使用NULL,除非确实是对真实数据进行建模的正确方法。

        ● 尝试使用相同的数据类型来存储相似或相关的值,尤其是在联接条件中使用这些值时。

        ● 注意可变长度字符串,它可能会导致临时表和排序的全长内存分配不乐观。

        ● 如果可能的话,尝试使用整数作为标识符。

        ● 避免使用一些传统的MySQL技巧,例如,指定浮点数的精度或整数的显示宽度。

        ● 小心使用ENUM和SET类型。它们很方便,但也可能被滥用,有时还很棘手。另外最好避免使用BIT类型。

        数据库设计是一门科学。如果你非常关注数据库设计,可考虑使用专用的源材料。(要进行深入学习,请参阅Michael J.Hernandez(Pearson)的Database Design for Mere Mortals。)

        还请记住,你的schema将随着业务需求和用户数据而发展,这意味着拥有一个强大的软件

生命周期来管理schema更改是使这种发展在组织中安全且可扩展的关键部分。

        

        上一篇:《第6章-1 数据类型

        下一篇:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天狼1222

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值