POLOXUE's BLOG

POLOXUE's BLOG

20 Feb 2024

数据库结构变更同步:增量 VS 差异

嗨!大家好,我是波罗学。本文是 Golang 三方库推荐第三篇,主要是闲扯,为后面两个工具做铺垫。系列查看:Golang 三方库

平时在开发项目时,常会需要改动数据库结构,比如说,有时候需要加个表,改个字段名,这是个挺常见的事。为了搞定这些改动,一般有两种做法:增量同步和差异同步。

今天,简单聊聊这两种同步方式,看看它们各自有啥优点和缺点。我曾经在工作中即用过增量同步,也用过差异同步。

增量同步

先说增量同步,这个方法挺直接的。就是每次你改了数据库,都会写一个迁移文件记录下来。想更新数据库的时候,就按这些文件的顺序,一步步来。

我来通过一个实际场景介绍下这种同步方式。

假设你有一个博客系统,现在需要为posts表增加一个views字段来记录每篇文章的浏览次数。使用增量同步,你会创建一个迁移文件,记录下这次变更。

1
2
3
- 20210101_add_views_to_posts.sql

ALTER TABLE posts ADD COLUMN views INT DEFAULT 0;

如果之后决定添加一个comments_count字段来记录评论数,你会创建另一个迁移文件:

1
2
-- 20210202_add_comments_count_to_posts.sql
ALTER TABLE posts ADD COLUMN comments_count INT DEFAULT 0;

使用增量同步工具,就会按照文件的顺序来更新数据库结构。我下篇文章介绍的一个 Go 实现的表结构同步同居 Goose 就是基于这种方式。

这种方式的好处在于,我们能很清楚地知道每次的改动,需要回头看的时候,也容易找。而且,这些迁移文件可以放到版本控制里,团队里的成员都能看到,一起协作。

不太好的地方是,时间一长,这些文件可能成堆积如山,管理起来就头疼了。特别是新起一个环境,得从头跑一遍所有的迁移,有时候还会中途卡壳。我自己就遇到过,为了让一个新环境跑起来,得一个一个检查哪里出了问题,中间还得修十几个迁移文件,那时候真是既烦躁又无奈。

针对这个问题,我原本是寄希望于找到一款支持类似 git squash 能力的工具,能把一段时间的 SQL 改动合并成一个文件,按发布版本管理迁移文件。这样至少文件少点,依赖问题也能减轻些。不过,貌似大多数增量迁移工具没有这个能力。当然,即使支持也支持缓解,并没有根治。

如果走手动合并的路线,版本控制和环境隔离就成了大问题,需要精心规划,多人审查来控制发布。

差异同步

差异同步呢,就比较关注起点和终点。

它看看你的数据库从现在到你想要的样子之间有啥不同,然后直接生成一个脚本,把数据库一次性改到你想要的样子。

还是以上面的增量同步中介绍的场景为例。假设你的posts表初始状态没有views和comments_count字段,目标状态需要这两个字段,使用差异同步工具,它会生成如下的SQL脚本:

1
2
3
ALTER TABLE posts
    ADD COLUMN views INT DEFAULT 0,
    ADD COLUMN comments_count INT DEFAULT 0;

这个脚本包含了将数据库从当前状态更新到目标状态所需的所有变更。

优点是管理起来轻松多了,不用像增量那样一大堆文件。对于那种经常改来改去的项目,用这个可以省不少事。

缺点是这种方式有时候没那么精确。自动生成的脚本偶尔可能也会有疏漏,需要人工检查一下。

虽然说,差异同步的方式有这样的缺点,但我们可以将生成差异文件交给专业的人和自动化流程检查,它也更容易标准化到 CI/CD 流程中,容易 linter 检查。

我也会介绍一个 Go 实现的基于这个方式的工具来完成这种操作。

实际操作建议

具体挑哪个方式,得看你的项目需要。如果你特别在意每一步的变化,喜欢细致控制,甚至是具体到个人,增量同步可能更合适。但如果你更看重效率,不想被一堆文件搞得头大,甚至希望能自动化流程。那就试试差异同步。

不管用哪种,我都有几个小建议:

非生产环境测试

在对数据库结构进行修改前,一定要在非生产环境进行彻底测试。这不仅是为避免直接在生产环境中引入潜在问题,更是为了确保新的变更不会破坏现有的数据或功能。特别是当你尝试合并增量迁移文件以简化管理时,测试成为了一个不可或缺的步骤。

版本控制记录

将数据库变更记录纳入版本控制系统是管理数据库迁移的另一个关键。这样做不仅能够保持团队成员之间的同步,还能提供一个详细的变更历史,方便回溯和审计。对于使用差异同步方式的项目,虽然变更可能是由当前与目标状态之间的差异自动生成的,但将迁移脚本的变更历史记录都保存下来了,可以追踪每次部署的具体内容。如果在未来遇到问题,这些记录也可以帮助快速定位问题的起源,从而简化故障排除过程。

尽量自动化

自动化迁移过程不仅可以提高效率,还能减少因手动操作导致的错误。通过使用CI/CD自动执行迁移,可以确保每次部署都经过相同的步骤,减少了人为失误的机会。此外,自动化测试可以与迁移过程结合起来,以自动验证每次变更的影响,确保迁移不会对现有系统造成意外的破坏。。

总结

管理数据库结构的变更是挺需要技巧的一件事。了解增量同步和差异同步的各自优劣,能让我们根据实际情况,选择更合适的方法。

对于我个人来说,增量同步的使用经历的确是不好受。一般情况下,我会优选差异同步。

本文来源于 POLOXUE's BLOG,地址: 数据库结构变更同步:增量 VS 差异
欢迎关注我的公众号: