专栏名称: CSDN
CSDN精彩内容每日推荐。我们关注IT产品研发背后的那些人、技术和故事。
51好读  ›  专栏  ›  CSDN

Swat.io如何在两年内从MySQL迁移到PostgreSQL

CSDN  · 公众号  · 科技媒体  · 2017-05-10 12:17

正文

作者 | Markus

翻译 | Aladdin


译者注:Swat.io是欧洲一家提供社交媒体解决方案的公司,总部在维也纳,以下为译文。


乍一看,这篇文章看起来像是标题党。但是我们不能否认一个事实,公司从MySQL到PostgreSQL迁移已经开始,因为MySQL越来越复杂了。


回想公司刚成立那会儿,我们团队只有三个人,没有太多的资源和精力投入到技术的基础架构上;如果你正处在一个小团队,那么迁移到PostgreSQL就是个不错的选择。


不可否认,MySQL有许多优点,没有它,我们公司就不会发展到今天这一步。但是随着时间的推移,它的缺点慢慢的掩盖了其优点。由于缺乏更深入的专业知识,我们始终依赖于Percona MySQL和Ubuntu LTS 14.04的机带版本,从未使用过外部工具,因为一旦使用这些,就必须有人学习,了解以及维护这些工作流程,这将是一个巨大的人力成本的投入。


我们对MySQL 5.6不满意的主要原因


  • 无法在线添加新的字段

    大表无法在线添加新字段的问题常常迫使我们每隔一个月就要暂停一次数据库服务器。而对于像pt-online-schema-change这样的在线DDL的第三方工具,我们又不是很了解,这让我们感到很崩溃;

  • 不能用一种可靠的方式在线添加索引
    事实上,MySQL 5.6开始支持在线添加索引了,但是在实际操作中,我们一直很紧张,因为你不知道这样的添加方式是否可靠,错误的操作会引起线上项目的巨大反应;

  • 5.6版本不支持json原生类型的字段(5.7.8版本开始引入);

  • 缺少CTE(公用表表达式)和窗口函数等数据库高级功能;


  • 在数据库超出最大连接数的地方,我们已经锁住了,但是我们不能在我们的系统中找到问题的根源,最后发现就是几百个连接执行的select语句造成的,最终我们手动杀死了这些查询进程。

还有另外几个看似不是问题的小问题,但是它们确实让我们感到不满:


  • 没有原生的布尔类型
    取而代之人们以Tinyint(0)来实现布尔类型,但是这样就需要所有适配器语言执行本地强制类型转换,或者至少配置其ORM/DataModels;


  • 使用mysqldump创建一个完整的数据库备份要花费了几个小时(3-4小时) 。
    另外,并行备份数据库也不是很容易;


  • 导入该数据库备份比创建备份所花时间更长(通常8-9小时);


  • DDL语句不是事务的一部分
    2014年前后,我们的前合作伙伴25th floor建议我们使用Postgres,实践证明,当我们的应用迁移到Postgres,并没有增加我们团队的资源消耗。

开启轻量级的Postgres?我们做到了!


我们遵循了建议,开始更深入的考察Postgres。为了简单起见,我们打算通过更改驱动程序来达到迁移的目的。但是,同志们,我们错了,2014年11月,我们提出了第一个完全迁移到Postgres的愿景的方案,标题为“[数据库]勇敢的新世界”。然而,这个方案有太多的问题,最终在半年后被抛弃了。


但是我们一直没有放弃。经过一番讨论和规划,我们决定将在新的swat.io分析引擎项目中引入Postgres。事实证明,这是一个绝妙的机会:一切从零开始,与现在的系统无关。唯一的缺点就是我们主要的数据仍然在MySQL中。要迁移到Postgres,就需要同步数据。虽然不是很完美,但是从商业角度来讲可以接受,从而为我们迁移的道路迈出了第一步。


这个项目需要花费了几个月时间完成,除了开发新的后端和UI代码之外,还给了我们足够的时间来学习新的数据库系统:


  • 如何将其集成到我们的开发人员虚拟机堆栈中?

  • 数据库角色概念如何运作?

  • 在写入密集型的负载下它的表现如何?

  • 我们可以多快地对新功能进行原型设计?

  • 当我们不满意查询性能,该如何调整它?

  • 怎样实现数据库的备份与恢复,以及它的工作原理?

  • 如何使用PHP和NodeJS与现有的系统进行整合?


镜像模式?我们失败了!


公司的分析引擎项目取得了成功,我们非常喜欢Postgres,但仍然无法迁移整个应用程序,我们尝试了另一种方法:


在我们的ORM中创建连接到Postgres的镜像模型。在每次保存MySQL模型后,我们将触发相同的保存到Postgres数据库中。在理论上听起来很好,实践中总是有空白或某些区域没有被正确的更新,我们不得不放弃这种方法。


继续小的尝试?我们做到了!


2015年夏季时,我们决定把一些记录表迁移到Postgres;但是这些数据只是些无关紧要的临时数据,所以放弃了数据迁移工作,直接迁移到新的数据库,并停用删除了相关的老数据库。


紧接着的尝试


在2015年8月左右,我们的团队再次对MySQL的使用表示无奈,并且尝试迁移应用程序代码库。这次尝试比第一次更加先进,一次真正“使用”几乎完整的应用程序。


只有一个“轻微”缺点:性能落后于MySQL!这在我们开发人员VM中甚至可以很容易地观测到。为此,我们进行了微型优化(例如禁用SSL连接),并开始大修查询。但是我们得出的主要问题是:我们的应用程序在页面加载期间(有时)会有成百上千个小型SQL语句的操作,而且每一个在Postgres中都有一点点慢,但是这一切还是在可容忍的范围内。


请注意,这个结论是未来数据库优化的主攻点:


  • 在数据库端执行更多操作(诸如:使用更合理的的复合查询等)

  • 更多的使用数据库(很多业务能够在客户端完成,但并不能表明它一定要在客户端完成 )。



令人尴尬的是,直到一年以后,我们才发现了这个罪魁祸首(CakePHP2 Postgres驱动程序开销问题),给我们带来如此多的需要优化的地方,我们深知,还有许多帮助改进的事情可以做,但是这在当时超出了我们的能力范围。


不幸的是,这次尝试在几个月内都没啥进展,最后几乎被遗忘。


挑战一切,永不放弃!


不过,随着时间的推移,新内部项目中就出现了一个问题:


我们是要在MySQL还是在Postgres中创建新的表?


使用InnoDB数据库引擎的外键功能来保持数据一致并不总是很容易,往往在不同数据库间同步数据时容易出错。但是感到庆幸的是,这些MySQL中的主要痛点都不复存在了:


  • 不管你的表有多大,100MB也好,100GB也好,一旦新字段允许为NULL,并且没有默认值的情况下,数据库默认添加一个空操作;

  • 添加新索引变动轻而易举,只要将它们设置成CONCURRENTLY ,然后你就完事了。








请到「今天看啥」查看全文