不久前,我经历了一次数据迁移项目。前几天,我跟一位架构师探讨了一下当时的各个步骤,和我所选择并进一步开发的解决方案。我觉得我应该告诉他一些信息 ,避免他日后迁移数据时踩坑。
在我们的交流中 ,我提到了数据迁移的各种难题和我们遇到的问题。现在我意识到,这些东西对许多从事数据迁移项目的人们来说都很有用。我听说这些是很常见的问题,多是那些开始数字化转型的公司容易遇到的 。数据迁移项目通常是一套解决方案,让你提取、转换旧数据,然后将其存储到新的系统中。
之前没想到的是,我从事软件工作以来只参与过一个数据迁移项目。感觉好像回到了我在学习 SQL 时挣扎的日子。那时的经历很有意思,你在 Oracle 和 MariaDB 上都使用 PL/ SQL ,并为此头痛不已。你只能自行猜测哪个是旧系统,哪个是光芒万丈的新系统。但今天不讲这个,今天讲我认为导致延迟交付的最大陷阱。观点是我自己的,但事情却是大家都会遇到的,等等等等。
1. 用 SQL 脚本做主要工具
这是昨天早上我忘了向同事强调的一个问题,今天早上它又在我脑海闪现。别误会,SQL 是强大的 数据 检索和显示工具。但是,当你有一个由多个开发人员组成的团队,并在同一个代码库上工作时,关键要确保你的更改能与其他代码很好地整合。
问题在于,要验证不同的场景 时 ,我们不能只花几秒钟或几分钟运行典型的单元测试。我们必须执行实际的迁移,因此我不会称之为“集成测试”,因为 集成测试的 环境与实际环境有所不同(后文会详细介绍)。
我们必须启动 docker 镜像,然后给将来要 用真实数据应对 的每种 场景 加载虚拟数据。我觉得我们的 Jenkins 构建一次要 2-3 个小时才能完成。这使本地开发更加困难,因为没有人愿意花 5 分钟内改代码然后花 2-3 个小时来测试。最开始我们改为只运行我们需要的那些测试用例。那时 CI 慢 到, 我甚至在上一年专门发了一个帖子讲这个事情 。最终,我们将时间降到了 40 分钟,仍然很慢,但考虑到我们正在处理的内容,可能这就是我们最好的选择了。
https://www.codingnagger.com/2019/01/31/slow-ci/
现在我不是 在谈我自己的经验 ,而是 在说 一些跟我讨论过的架构师 的看法 ,他们在那个项目 期间,甚至项目结束之后都向我建议 ,用一种实际的编程语言可以使我们免于这种痛苦:你可以 测试任意组件,完整的检索 、转换和加载 操作 只需几秒钟就够了。然后你再对理想路径进行一次集成测试。我们本来可以把 CI 构建控制在一分钟之内的,从而节省很多时间。
2. 源字段和目标字段对不上
字段不匹配是很痛的痛点。我不是指从源数据字段到目标数据字段的对应错误,而是指字段对应没问题,但目标字段类型不对。由于数据 的 敏感 性 ,我们研究解决方案时接触不到真实数据。
所以这种问题只有到了在生产环境运行时才会暴露出来。你可能会有一些源字段是字符串类型的,但目标字段却是整型的。当所有测试数据都是数值时不会有问题,但当在几百万实体中出现哪怕一两条包含字母时,就全都完了。还有些时候数据会被截断,因为目标字段所能表达的值范围比源字段要小。这种问题不是数据迁移工程的责任,因为目标系统不是我们设计的,但实际上我们在交付数据迁移方案时却不得不去修复这种问题。是的,现实并没有那么理想。
所以在这里我要强调的是,如果你要构建一个系统的新版本,请确保新的数据库字段的类型和格式都能匹配源数据。我们不能截断地址或电话号码,尤其是当我们系统需要这些信息时。
3. 与其他团队边界不明确
当时,我的团队是做数据迁移的。我们设计了一个解决方案,把数据从这里迁移到那里。但如上文所述,我们有时不得不修复目标数据库的问题,这些问题都是其他团队为各种功能折腾出来的。最重要的是,我不明白我的团队怎么就变成了其他团队的测试数据提供者。反正 这些团队不会把所有的测试数据汇总在一起以便测试其功能,而是会来找我们为他们生成随机的测试数据。
回想起来,这么做真蠢。因此,我们构建的测试框架中有一个类用于生成数据。在 开发时,我们把这些数据存到源数据库里,然后运行迁移过程,提取、转换这些数据,并把它们存到目标数据库里。接着再从目标系统中导出这些数据发送给那些团队。我们不得不这么做,因为我们不想在我们的职责范围之外制造数据。但是,我认为我们做的太多了。我们应该把 底线控制 在“请您自行创建测试数据”上。
虽然帮助他人 也是可以的 ,但我们不能在自己本职工作都没做完的情况下这么做。最后的结果就是,我们负责了整个工程的三个主要部分:数据迁移、修复目标数据库的问题、给每个人生成测试数据。
4. 不同环境的设置
我记得当时我没有过多考虑 各种部署 环境的不同设置。从开发环境到预发布环境,再到生产环境,它们 会 有很多差异。显然,我们为此付出了代价。你可能会认为不同版本间的 Oracle 数据库或 MariaDB 数据库应该不会有什么大问题吧?但如果我告诉你下个版本跟这个版本的差异会破坏掉你所有的 SQL 脚本呢?就像必须把 VALUES 替换成 VALUE。
想象一下迁移工具在你本地运行得好好的,接下来你把它推送到一个缓慢的 CI 流程 。然后你再把它发布到一个环境,运行迁移过程并检查 ,没什么问题 。结果到生产环境出问题了,因为生产环境的 MariaDB 版本太老。此外,生产环境还是个 EC2 实例,而预发布环境则是 RDS。
这个项目在开发环境和在生产环境的变量设置完全一致,但我还是被它们输出的差异惊到了。为 了 在不同集成环境里都能工作而到处改代码 ,那些痛苦你都逃开了 。生产环境的配置 本应能 证明你的解决方案可以在生产环境工作,但 其实 它跟真实的生产环境配置一点也不像, 这肯定就会出问题 。这绝对是我在这次经历中得到的最大一笔经验。
5. 总结
我将在余生中继续学习从旧项目获得的经验教训。我甚至会重温这篇博客文章来确保我不会忘记这些经验教训,因为它们在我下次进行数据迁移时还是非常有用的。更妙的是,其中一些经验教训不仅仅可以用于数据迁移,还可以应用于其他方面。
即使这次我没有去找个工具来做, 本文谈到 的 这些 经验也让我坚信应该找个好工具来做好工作。信任已有信息固然很好,但也不妨 去看看周围 ,对自己也没有什么坏处。有时这些工具并不比 SQL 查询慢。
其次,尽可能确保开发环境的设置与生产环境匹配。这将避免许多集成问题。
最后,当职责明确了之后,应避免给自己揽更多的活儿,它们会妨碍你的本职工作。塞尔吉奥·拉莫斯(Sergio Ramos)并不是世界上最好的后卫,因为他本赛季得分超过菲尔米诺。最好的后卫应该是先做好自己擅长的防守工作,然后偶尔进进球。