为什么Uber优步数据库从Postgres切换到MySQL?

早期Uber是使用Python+Postgres作为整体型后端应用,后来,Uber架构切换到了微服务模型以及新的数据平台,之前使用的是Postgres,现在使用Schemaless,一种基于MySQL的带有分表层的新异数据库。

这篇文章
Why Uber Engineering Switched from Postgres to MyS解释了切换原因:

遭遇Postgres的问题是:
1.低效率的写操作
2.低效率的数据复制
3.表中断问题
4.可怜的复制MVCC支持
5.难于升级到新版本

Uber在文章中使用举例证明了Postgres索引的低效原因,第一索引和第二索引都是指向同一个磁盘元偏移,当元组定位改变时,所有的索引都必须更新。这也是Postgres写操作低效的原因。

复制方面低效:当插入一个新行记录到表中时,Postgres在流复制激活情况下会复制它,为了防止崩溃后恢复,数据库已经维持了一个write-ahead日志(WAL),使用它实现两段事务2PC,数据库即使在流复制没有激活时,必须维持WAL,因为WAL是实现ACID的原子性和持久性(durability)。

如果数据库发生意外崩溃,WAL就会实现崩溃恢复,而Postgres实现流复制是通过发送WAL从主节点到从节点的,这种崩溃恢复和流复制的区别是当使用流复制时,复制数据将处于热备用模式,以便服务于读操作查询。而Postgres数据库实际在崩溃恢复模式时是拒绝服务于任何查询操作的,直至其完成崩溃恢复过程。

另外,因为WAL已经设计为崩溃恢复,它包含低级别有关磁盘更新的信息,在主从复制过程中如果你暂停复制,那么实际磁盘复制数据会精确停在某个byte字节处,因此会发生主从数据不匹配问题,这时使用rsync能够解决复制中断问题。

Uber陈述了以上Postgres设计的瑕疵后,具体地谈了以下问题:
1.Write Amplification导致多次物理更新。
2.复制问题,第一个问题造成了复制问题,因为复制是在磁盘发生变化时进行的。
3.数据中断问题,在数据库扩容时遭遇Postgres 9.2的bug,引起了丢失一部分WAL记录,因为这个 Bug,一些记录被标志为不激活。
4.Postgres并没有真正的MVCC支持。
5.在不同Postgres版本之间是无法进行主从复制的。

最后Uber谈了MySQL架构:
MySQL的第二索引指向第一索引记录,而第一索引是持有磁盘记录行定位,如果发生行偏移,只有第一索引需要更新。

在复制方面,MySQL支持基于状态复制,基于行复制和两者混合复制。

MySQL其他优点:
1.Buffer Pool
2.MySQL使用一个连接一个线程,而Postgres使用一个连接一个进程,进程显然比线程更加耗费内存,更昂贵。

更详细见原文:
Why Uber Engineering Switched from Postgres to MyS