加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

为PostgreSQL讨说法:浅析Uber切换MySQL

发布时间:2020-12-13 18:17:03 所属栏目:百科 来源:网络整理
导读:《为PostgreSQL讨说法:浅析Uber切换MySQL》要点: 本文介绍了为PostgreSQL讨说法:浅析Uber切换MySQL,希望对您有用。如果有疑问,可以联系我们。 原题目为: 为PostgreSQL讨说法 - 浅析《UBER ENGINEERING SWITCHED FROM POSTGRES TO MYSQL》 配景 最近有

《为PostgreSQL讨说法:浅析Uber切换MySQL》要点:
本文介绍了为PostgreSQL讨说法:浅析Uber切换MySQL,希望对您有用。如果有疑问,可以联系我们。

原题目为:为PostgreSQL讨说法 - 浅析《UBER ENGINEERING SWITCHED FROM POSTGRES TO MYSQL》

配景

最近有一篇文档,在国外闹得沸沸扬扬,是关于UBER使用mysql替换postgres原因的文章.

https://eng.uber.com/mysql-migration/

文章涉及到PG数据库的部分,论点过度的浮于外面,没有深入的理解和分析.

很容易导致用户对PostgreSQL产物的误解.

另外还有一篇翻译的文档,则看起来已经完全变味.

http://www.jdon.com/48216

隐约感觉到一股黑PG的势力袭来.

为了让用户更清楚的认识涉及技术的本色,我打算写一篇浅析的文章,深入浅出的讲讲个中道理.

uber在文章论述的遇到的PG问题

We encountered many Postgres limitations:

  • Inefficient architecture for writes

  • Inefficient data replication

  • Issues with table corruption

  • Poor replica MVCC support

  • Difficulty upgrading to newer releases

我接下来会依依介绍其原理,以及文章内容存在的问题.

1. Inefficient architecture for writes

uber文章的观点

PG的MVCC机制,更新数据为新增版本,会带来两个问题

  • SSD的写放大

  • 索引的写放大

本文观点

事实并不是MVCC的问题,所有的数据库只要支持并发读写,就必要多版本,只是版本管理的手段可能不一样.

有通过回滚段管理的,也有通过多版本(MVCC)进行管理的.

原理剖析

基于回滚段管理的数据库

当更新一条记录时,有些数据库必要将整个数据块拷贝到回滚段区域(有些是基于逻辑行的拷贝,则拷贝到回滚段的是记录).

注意写回滚段也是会发生REDO写操作的.

  • 更新可能在当前的row进行.

    这种情况,只要索引字段不变化,索引就不必要变.

    如果索引字段值产生变化,索引也要变化.

    为PostgreSQL讨说法:浅析Uber切换MySQL

  • 如果更新后的记录超过本来行的长度,可能在本页找一块空闲区域(如果能装下),也可能要到其他页找一块区域进行更新,有擦除旧记录,写入新纪录的写操作.

    不管怎样,索引都要变化.

    为PostgreSQL讨说法:浅析Uber切换MySQL

基于回滚段的数据库,如果要回滚事务,开销会很大(特别是当事务修改的数据量很大时),因为要从回滚段将整个块拷贝到数据文件(基于逻辑行拷贝的回滚则是类似重新来一遍UNDO事务的SQL操作,同时还必要擦除之前更改的行).

代价非常高 .

基于MVCC的数据库

当更新一条记录时,发生一个新的版本.

  • PostgreSQL 会优先使用在当前页更新(HOT),即在当前页进行更新,不管行长度是否产生变化.

    这种情况,索引也要变化.

    (hot时,索引不变,通过HEAP页内旧item指向新item来做到定位到新的记录)

    为PostgreSQL讨说法:浅析Uber切换MySQL

  • 如果未在当前页更新,则索引才必要变化

    (通过配置表的fillfactor,可以大大减少这种情况的发送,尽量走HOT)

    如果读者还是担心这个问题,我们可以做一个压测试验,看看到底会不会更新索引,会不会对更新造成性能影响如何?

    1000万数据,9个字段,8个索引,更新此中的mod_time字段.

    postgres=# create table tbl(id int,mod_time timestamp(0),c1 int,c2 int,c3 int,c4 int,c5 int,c6 int,c7 int) with (fillfactor=80);CREATE TABLETime: 1.906 ms

    postgres=# insert into tbl select i,clock_timestamp(),i+1,i+2,i+3,i+4,i+5,i+6,i+6 from generate_series(1,10000000) t(i);INSERT 0 10000000Time: 14522.098 ms

    postgres=# create index idx1 on tbl(c1) with (fillfactor=80);CREATE INDEXTime: 3005.753 ms

    postgres=# create index idx2 on tbl(c2) with (fillfactor=80);CREATE INDEXTime: 2793.361 ms

    postgres=# create index idx3 on tbl(c3) with (fillfactor=80);CREATE INDEXTime: 2804.031 ms

    postgres=# create index idx4 on tbl(c4) with (fillfactor=80);CREATE INDEXTime: 2856.954 ms

    postgres=# create index idx5 on tbl(c5) with (fillfactor=80);CREATE INDEXTime: 2895.643 ms

    postgres=# create index idx6 on tbl(c6) with (fillfactor=80);CREATE INDEXTime: 2932.394 ms

    postgres=# create index idx7 on tbl(c7) with (fillfactor=80);CREATE INDEXTime: 2939.927 ms

    postgres=# alter table tbl add constraint pk_tbl primary key(id) with (fillfactor=80);ALTER TABLETime: 3292.544 ms

    记录下当前表的大小和8个索引的大小

    postgres=# dt+ tbl

    List of relations

    Schema | Name | Type | Owner | Size | Description

    --------+------+-------+----------+--------+-------------

    public | tbl | table | postgres | 919 MB | (1 row)

    postgres=# di+

    List of relations

    Schema | Name | Type | Owner | Table | Size | Description

    --------+-----------------------+-------+----------+------------------+--------+-------------

    public | idx1 | index | postgres | tbl | 241 MB | public | idx2 | index | postgres | tbl | 241 MB | public | idx3 | index | postgres | tbl | 241 MB | public | idx4 | index | postgres | tbl | 241 MB | public | idx5 | index | postgres | tbl | 241 MB | public | idx6 | index | postgres | tbl | 241 MB | public | idx7 | index | postgres | tbl | 241 MB | public | pk_tbl | index | postgres | tbl | 241 MB |

    全力压测30分钟,更新mod_time字段

    $ vi test.sql

    setrandom id 1 10000000update tbl set mod_time=now() where id=:id;

    压测开始

    pgbench -M prepared -n -r -P 5 -f ./test.sql -c 48 -j 48 -T 1800

    压测成果,更新速度持续在 13万/s 以上. 这个压力应该可以覆盖很多的用户吧.

    progress: 5.0 s,133373.6 tps,lat 0.357 ms stddev 0.269progress: 10.0 s,133148.2 tps,lat 0.359 ms stddev 0.310progress: 15.0 s,134249.0 tps,lat 0.356 ms stddev 0.299progress: 20.0 s,131037.9 tps,lat 0.364 ms stddev 0.341progress: 25.0 s,135326.3 tps,lat 0.353 ms stddev 0.292progress: 30.0 s,135023.9 tps,lat 0.354 ms stddev 0.289......

    progress: 1385.0 s,135997.9 tps,lat 0.351 ms stddev 0.261progress: 1390.0 s,133152.5 tps,lat 0.359 ms stddev 0.302progress: 1395.0 s,133540.7 tps,lat 0.357 ms stddev 0.287progress: 1400.0 s,132034.8 tps,lat 0.362 ms stddev 0.314progress: 1405.0 s,135366.6 tps,lat 0.353 ms stddev 0.266progress: 1410.0 s,134606.6 tps,lat 0.355 ms stddev 0.280.....

    progress: 1855.0 s,134013.7 tps,lat 0.356 ms stddev 0.298progress: 1860.0 s,132374.8 tps,lat 0.361 ms stddev 0.306progress: 1865.0 s,133868.3 tps,lat 0.357 ms stddev 0.282progress: 1870.0 s,133457.1 tps,lat 0.358 ms stddev 0.303progress: 1875.0 s,133598.3 tps,lat 0.357 ms stddev 0.297progress: 1880.0 s,133234.5 tps,lat 0.358 ms stddev 0.297progress: 1885.0 s,131778.9 tps,lat 0.362 ms stddev 0.319progress: 1890.0 s,134932.2 tps,lat 0.354 ms stddev 0.274......

    progress: 2235.0 s,135724.6 tps,lat 0.352 ms stddev 0.284progress: 2240.0 s,136845.0 tps,lat 0.349 ms stddev 0.256progress: 2245.0 s,136240.6 tps,lat 0.350 ms stddev 0.264progress: 2250.0 s,136983.2 tps,lat 0.348 ms stddev 0.248progress: 2255.0 s,137494.5 tps,lat 0.347 ms stddev 0.251......

    压测结束后,查看表和索引的大小,如果按UBER文中指出的,会更新索引,但实际上,成果说话,表和索引根本没有膨胀.

    UBER 文章对用户的误导不攻自破.

    表的大小未变化

    postgres=# dt+

    List of relations

    Schema | Name | Type | Owner | Size | Description

    --------+------------------+-------+----------+---------+-------------

    public | tbl | table | postgres | 919 MB | 索引的大小也未变化

    postgres=# di+

    List of relations

    Schema | Name | Type | Owner | Table | Size | Description

    --------+-----------------------+-------+----------+------------------+--------+-------------

    public | idx1 | index | postgres | tbl | 241 MB | public | idx2 | index | postgres | tbl | 241 MB | public | idx3 | index | postgres | tbl | 241 MB | public | idx4 | index | postgres | tbl | 241 MB | public | idx5 | index | postgres | tbl | 241 MB | public | idx6 | index | postgres | tbl | 241 MB | public | idx7 | index | postgres | tbl | 241 MB | public | pk_tbl | index | postgres | tbl | 241 MB |

小结

  • 基于回滚段的数据库,在更新数据时SSD写放大 > 100%(因为回滚段是必定要写的,并行写回滚段的操作也需要写REDO);而基于MVCC的数据库,SSD写放大的概率低于100%(因为可能发生HOT,发生在当前页),而且旧记录只改行的xmax标记,产生的REDO极少.

  • 基于回滚段的数据库,在删除数据时SSD写放大是100%(因为回滚段是必定要写的,SSD写放大的概率为0 (因为只需要改一下行头部的xmax的标记).

  • 基于回滚段或MVCC的数据库,索引的写放大,都与是否产生行迁移有关,概率差不多.

  • 基于回滚段的数据库,同时还必要擦除之前更改的行).

  • 基于MVCC的数据库,事务回滚非常快,因为不必要拷贝行或者数据块,也不必要修改已更新的记录,只是记录clog时将当前事务标记为ABORT即可,也就是说只必要改2个比特位.

  • PG的HOT技术完美的办理了索引更新的问题,根本不存在UPDATE就一定需要更新索引的问题.

彩蛋

  • PostgreSQL TOAST机制

    PostgreSQL的TOAST机制,可以将变长类型的值,自动压缩存储到另一片区域,通过内部的POINT指向,而不影响行的其他值. 例如存储文档,或者图片的表,如果这个表上有一些字段要更新,有一些字段不要更新,那么在更新时,PostgreSQL数据库会有非常大的优势,因为行很小.

    为PostgreSQL讨说法:浅析Uber切换MySQL

    基于回滚段的数据库,必要拷贝旧的记录或数据块到回滚段,记录或块越大,这个开销越大.

    为PostgreSQL讨说法:浅析Uber切换MySQL

    存储文档、图像、非布局化数据,使用PostgreSQL很有优势.

  • MySQL innodb是基于B+树的存储,当PK数据随机数据写入时存在巨大写放大,因为常常要分裂,不仅影响插入速度和查询速度,同时数据存放也会变得非常无序.

    即使按PK顺序扫描时,也可能呈现大量的离散IO.

    为PostgreSQL讨说法:浅析Uber切换MySQL

    基于B+树布局的存储,为了提高插入速度,如果使用index cache的话,则影响并发的查询,因为查询时要先合并索引.

    为PostgreSQL讨说法:浅析Uber切换MySQL

    另一方面,B+树的存储,必需要求表需要一个PK(即使表没有PK的需求,也要硬塞一个PK列进来),secondary index则指向这个PK.

    如果PK发生更新,则所有的secondary index都要更新,也便是说,为了保证secondary不更新,务必确保PK不更新.

    如果要对secondary index进行范围扫描,其实物理的扫描上是离散的.

    为PostgreSQL讨说法:浅析Uber切换MySQL

    所以uber本文提出的,secondary index 不需要变更的好处,其实背后是有以上代价存在的(例如必定要加PK,插入速度更慢,插入时PK不能随机否则分裂带来的IO巨大,使用secondary index范围扫描时会造成离散的IO等弊端),把原理,代价都交代清楚,才能看得更清楚.

    PostgreSQL 有几种办法来消除这种离散IO.

    1. bitmap scan,获取heap tuple前,先根据ctid的blockid排序然后再从heap获取记录,以获得物理上次序的扫描.

    为PostgreSQL讨说法:浅析Uber切换MySQL

    2. cluster by index,将表的物理存储顺序依照索引的顺序来存放,从而使用该索引扫描时,则是顺序的扫描.

    为PostgreSQL讨说法:浅析Uber切换MySQL

  • PostgreSQL的表是基于HEAP存储的,不存在以上B+树存储的问题,随便怎么插入,速度都很快.

  • SSD的原子写,通常SSD写入时是以最小单位为4K的写入,即使修改很小的数据.

    那么以directio或buffer io为主的数据库,哪个对SSD的伤害更大呢?

    对于directio的数据库,因为每次都是真实的伤害,而buffer io的数据库,OS层还会合并IO,可以大幅降低SSD的真实写(os 层调整vm.dirty_background_ratio可以调整写频率,从而影响合并粒度).

    PostgreSQL的shared buffer管理是基于buffer io的管理,对SSD来说是一种很好的掩护,有兴趣的童鞋可以测试验证一下.

    为PostgreSQL讨说法:浅析Uber切换MySQL

2. Inefficient data replication

uber文章的观点

PG的复制低效,有写放大.

本文观点

PostgreSQL的流复制非常高效,延迟几乎为0,同时还支持流的压缩和加密传输,很多企业用流复制来实现异地容灾,HA,读写分离的应用场景.

同时PostgreSQL也支持逻辑复制(>=9.4支持流式逻辑复制,<9.4的版本则支持基于触发器或者基于异步消息的逻辑复制).

原理剖析

  • 问题反驳 1 (复制低效)

    我第一次听说PG的复制低效的,要知道PG的复制是业界有名的高效,延迟极低(关键是复制延迟与事务大小无关),网络好的话,几乎是接近0的延迟.

    PostgreSQL流复制原理

    即时唤醒,流式复制,所以延迟极低.

    为PostgreSQL讨说法:浅析Uber切换MySQL

  • 问题反驳 2 (REDO写放大)

    基于回滚段的数据库,在更新时,拷贝到回滚段的旧版本,是要写REDO的.

    而基于MVCC的数据库,旧版本仅仅需要写修改行头bit位的REDO,所以基于MVCC的数据库,更新时写入的REDO应该是基于回滚段的数据库的一半甚至更少(好比基于物理的回滚段要拷贝整个块,产生的REDO也很大).

    为PostgreSQL讨说法:浅析Uber切换MySQL

    同时,由于基于回滚段的数据库回滚时,要将回滚段的数据拷贝回数据文件,是会发生REDO的,这一点,基于MVCC的数据库不存在这种写放大的问题.

    为PostgreSQL讨说法:浅析Uber切换MySQL

  • 问题反驳 3(复制流量放大)

    基于REDO的物理复制,意思便是要把REDO复制一份到备库.

    所以REDO写了多少,就要复制多少到备库,网络的流量也是这样的.

    另一种是基于REDO的逻辑复制,需要复制的数据不仅仅包含新的数据,还要包含旧的版本数据(PK或者full row).

    可能一条记录更新前和更新后的数据都要复制.

    对更新操作来说,物理复制,不必要复制旧的记录(因为产生REDO的仅仅是XMAX的变化)过去,而逻辑复制则必要复制旧的记录过去.

    另外需要注意的是,目前PG的垃圾回收也是以物理恢复的形式复制的,在实现上还有改进空间,好比通过逻辑的方式复制垃圾回收(只复制block id),可以大大减少网络传输的流量.

    为PostgreSQL讨说法:浅析Uber切换MySQL

    而 uber 文章并没有指出,事实上 MySQL 目前只支持逻辑复制,而且如果要开启逻辑复制,不仅仅要写redo,同时还要写 binlog,等于写了双份日志,这个写放大也是很大的.

    MySQL redo 用于恢复数据库,binlog用于复制.

    为PostgreSQL讨说法:浅析Uber切换MySQL

    自PostgreSQL 9.4开始,PG内核层就同时支持物理复制和逻辑复制,并且仅仅写一份日志就能同时支持物理以及逻辑复制.

    在9.4版本之前,则可以通过其他软件进行逻辑复制(例如Londiste3,slone-I)

    为PostgreSQL讨说法:浅析Uber切换MySQL

    逻辑复制有一个弊端,被复制的表必定要有PK. 物理复制不存在这个问题 .

    逻辑复制另一个弊端,大事务导致主备的延迟非常大,因为备库必定要等主库事务结束,备库才能开始回放该事务.物理复制不存在这个问题 .

小结

  • PG的复制是业界有名的高效,几乎是接近0的延迟.

  • 基于MVCC的数据库,就版本仅仅需要写修改行头bit位的REDO,更新时写入的REDO应该是基于回滚段的数据库的一半甚至更少(好比物理回滚段要拷贝整个块,产生的REDO也很大).

  • 对更新操作来说,基于REDO的物理复制,不必要复制旧的记录过去,而逻辑复制则必要复制旧的记录过去,物理复制产生的网络流量更小.

  • 逻辑复制有一个弊端,必定要PK. 物理复制不存在这个问题 .

  • 逻辑复制另一个弊端,备库才能开始回放该事务. 物理复制不存在这个问题 .

彩蛋

  • PostgreSQL可以开启协议层压缩,同时可以选择是否加密传输,压缩传输REDO.更高效,更平安.

  • PG的用户如果有主备环境,可以关闭FULL_PAGE_WRITE,产生的REDO更少(第一次更新的PAGE不必要写FULL PAGE).

    但是必要注意,如果关闭了FPW并且主库因主机问题或在OS问题挂了,必要从备份环境恢复.

  • PG用户,可以将checkpoint拉长,减少FULL PAGE的发生,从而减少REDO的发生.

  • PG的用户,如果必要从PG或者MYSQL复制到阿里云的rds PG,可以使用阿里dbsync插件,目前支持全量复制,增量的逻辑复制正在开发中.

3. Issues with table corruption

uber文章的观点

用户在使用PG 9.2 时,因为主备切换,导致了一些数据问题.

本文观点

UBER在文中并没有描述清楚这个问题的始末,如何复现,同时也没有听说过PG的其他用户遇到这样的问题.

并且我在测试环境模拟TPC-B,同时不停的进行主备切换,也没有遇到类似问题.

PG的物理复制是可以保证主备完全一致的.

uber给出的观点心理暗示比拟可怕.

PG一直以来便是一个以稳定性和功能强大著称的数据库,在企业市场有非常好的口碑.

国内的银行,运营商,保险,互联网公司都有在核心环境使用 ;

  • 安全科技、阿里巴巴、高德、去哪儿、腾讯、用友、阳光、中移动、探探、智联、典典、华为、斯凯、通策医疗、同花顺、核电、国家电网、邮储银行、友盟、莲子......

海外的汽车生产巨头,政府部分,医疗,物流等各个行业也都有非常多的用户 .

  • 生物制药 {Affymetrix(基因芯片),美国化学协会,gene(布局生物学应用案例),…}

  • 电子商务 { CD BABY,etsy(与淘宝类似),whitepages,flightstats,Endpoint Corporation …}

  • 学校 {加州大学伯克利分校,哈佛大学互联网与社会中心,.LRN,莫斯科国立大学,悉尼大学,…}

  • 金融 {Journyx,LLC,trusecommerce(类似支付宝),日本证券交易交所,邮储银行,同花顺…}

  • 游戏 {MobyGames,…}

  • 政府 {美国国家气象局,印度国家物理实验室,联合国儿童基金,美国疾病控制和预防中心,美国国务院,俄罗斯杜马…}

  • 医疗 {calorieking,开源电子病历项目,shannon医学中心,…}

  • 制造业 {Exoteric Networks,丰田,捷豹路虎}

  • 媒体 {IMDB.com,美国华盛顿邮报国会投票数据库,MacWorld,绿色和平组织,…}

  • 零售 {ADP,CTC,Safeway,Tsutaya,Rockport,…}

  • 科技 {Sony,MySpace,Yahoo,Afilias,APPLE,富士通,Omniti,Red Hat,Sirius IT,SUN,国际空间站,Instagram,Disqus,…}

  • 通信 {Cisco,Juniper,NTT(日本电信),德国电信,Optus,Skype,Tlestra(澳洲电讯),中国移动…}

  • 物流 {SF}

小结

仅凭一个没有始末的结论,似乎很难阐明什么.

基于逻辑复制的数据库,主库压力大时通常会遇到备库追不上.

又或者因为某些原因导致主备纷歧致,即使发现了,可能并没有很好的修复手段,因为你不知道该以哪个数据为准.

逻辑复制导致主备纷歧致的原因较多,例如 主库执行失败,备库执行成功,或者备库执行成功,主库执行失败.

又或者 主库和备库的环境纷歧致,例如字符集,或者其他的,都非常容易导致主和备的纷歧致.

对于要求主备严格一致的场景,强烈建议使用物理复制.

4. Poor replica MVCC support

uber文章的观点

PG备库的MVCC支持较差,查询会与恢复堵塞

本文观点

首先,PG的备库分两种,一种是物理备库,一种是逻辑备库.

对于逻辑备库来说,与MYSQL的恢复机制是一样的,既然是一样的就不必要讨论了.

UBER文章说的 查询会与恢复堵塞,说的是物理备库,但必需纠正一个观点,查询是否堵塞恢复,是要论看场景的,况且堵塞的情况极为少见,还有一点要注意,逻辑复制也会有堵塞.

原理剖析

物理复制,什么情况下查询会堵塞、或与恢复冲突?

当以下操作产生的REDO被复制到备库,而且备库准备拿这些REDO来恢复时.

  • Access Exclusive locks taken on the primary server,including both explicit LOCK commands and various DDL actions,conflict with table accesses in standby queries.

    主库的拜访排它锁,与备库对应的锁产生冲突.

    例如主库truncate a表,备库查询a表.

    这种情况的冲突面很窄.

  • Dropping a tablespace on the primary conflicts with standby queries using that tablespace for temporary work files.

    主库删除表空间,备库使用这个表空间产生临时文件. 例如主库删除TBS,备库的一个大的查询必要写临时文件,并且这个临时文件是写到这个表空间的.

    这种情况非常少见,也很容易规避,新建一个临时表空间不要删除即可.

  • Dropping a database on the primary conflicts with sessions connected to that database on the standby.

    主库删除数据库,备库刚好连在这个数据库上.

    这种情况也非常的少见.

  • Application of a vacuum cleanup record from WAL conflicts with standby transactions whose snapshots can still "see" any of the rows to be removed.

    主库回收dead tuple的REDO,同事备库当前的query snapshot必要看到这些记录.

    这种情况可以通过参数控制,恢复优先,或查询优先. 可以配置时间窗口.

    并且这种冲突出现的概率也非常的小,除非用户在备库使用repeatable read,同时是非常大的事务.

    而通常用户用的都是read committed.

  • Application of a vacuum cleanup record from WAL conflicts with queries accessing the target page on the standby,whether or not the data to be removed is visible.

    同上,但是当query拜访的页就是要清理垃圾的页时,也是有冲突的.

    这是物理复制与逻辑复制唯一有差其余地方,但是对现实场景来说,这种情况出现的概率也不大.

对于PG来说,主备冲突导致的备库延迟,绝对没有MySQL逻辑复制在碰到大事务时那么可怕,逻辑复制遇到大事务,导致的延迟是很严重.

在现实应用场景中,很少有用户担心PG的备库延迟,即使有短暂的冲突,因为是基于块的恢复,恢复速度是很快的,马上就能追平(只要备库的IO才能够好,通常追平是瞬间完成的).

难道逻辑复制就不会呈现查询与恢复的堵塞、冲突吗?

当然也会有冲突

逻辑复制,什么情况下查询会堵塞、与恢复冲突?

  • 备库发起一个repeatable read的事务,由于备库赓续的恢复,备库的该查询事务有可能因为snapshot too old失败.

  • 主库发起的DDL语句,回放时会与备库的查询冲突,DDL的回放会被完全堵塞.

  • 主库删除一个数据库,回放时如果备库正好连在这个数据库上,发生冲突.

小结

基于物理复制或逻辑复制,只要备库拿来使用,都有可能呈现查询与恢复冲突的情况.

PG对于冲突的处置非常的人性化,你可以选择恢复优先 or 查询优先,设置时间窗口即可.

同时PG还支持备库的QUERY反馈机制,主库可以根据备库的QUERY,控制垃圾回收的延迟窗口,避免QUERY和垃圾回收的冲突.

5. Difficulty upgrading to newer releases

uber文章的观点

PG的跨版本升级较难,跨版本不支持复制

本文观点

看起来文章的作者或者UBER里可能没有熟悉PG的人,PG的大版本升级的途径很多,也很便利.

我这里给出两个办法

1. 办法1,通过迁移元数据的方式升级,这种升级方式,取决于元数据的大小(即数据结构,函数,视图等元信息)所以不管数据库多大,都能很快的完成升级.

例如以10万张表,1万个函数,1000个视图为例,这样的元数据大小可能在几十MB的水平. 自动化水平高的话,导出再导入应该可以控制在分钟级别完成.

关键是它能支持原地升级,也就是说,你不必要再准备一套环境,特别是数据库非常庞大的情况下,再准备一套环境是很恐怖的开销.

当然,如果企业有环境的话,为了保险,通常的做法是,复制一个备库出来,在备库实现原地升级,然后激活备库转换为主库的角色.

备库升级结束后,再升级老的主库,由于只动到元数据,所以主备的差异很小,rsync一小部门数据给老的主库,就能让老的主库实现升级,同时将老的主库切换成备库即可.

简单的几步就完成了主备的大版本升级.

为PostgreSQL讨说法:浅析Uber切换MySQL

基于pg_upgrade的大版本升级可以参考我以前写的文章

http://blog.163.com/digoal@126/blog/static/1638770402014111991023862/

http://blog.163.com/digoal@126/blog/static/163877040201341981648918/

2. 办法2,通过逻辑复制增量平滑升级,与MySQL的升级办法一样,也很便利,但是要求一定要准备一个备库环境,如果数据库已经很庞大的话,总的升级时间会比较漫长.

对于 >= 9.4的版本可以使用PG内置的逻辑复制.

小于9.4的版本则可以使用londiste3或者slony-I.

PG跨版本支持复制,并且支持的很好.

对于>=9.4的版本,可以用基于流的逻辑复制.

对于<9.4的版本,可以使用londiste3,slony-I.

小结

每种数据库都要去深入了解,才能去办理业务上面对的问题.

每种数据库存在即有存在的理由,有它适合的场景,MySQL和PostgreSQL发展这么多年,都有各自的用户群体,相互都有学习和借鉴的地方,作为数据库内核工作者,要多学习,把数据库做好,把最终用户服务好才是王道,也许下一代的数据库引擎便是PostgreSQL和MySQL杂交的,看看阿里云ApsaraDB接下来会放什么招吧 .

没有深入探讨问题的根源就抛观点,是纰谬的,容易被拿去当枪使,对整个开源行业没什么好处 .

UBER颁发的该文章对PG的论点过于表面和片面,读者要多思考,别被拿去当枪使了还不知道 .

基于线程和进程的讨论太多,PG基于进程,优势是非常强壮,所以PG的扩展能力极强,看看PG那无数的插件就知道了,是一个贴近用户的,高度可定制化的数据库.本文末尾的推荐阅读也包括了大量通过插件方式扩展PG功能的文章.

本文仅对uber发文的PG部门作出解释,网友可以多多交流.

更多深度技术内容,请存眷云栖社区微信公众号:yunqiinsight.

《为PostgreSQL讨说法:浅析Uber切换MySQL》是否对您有启发,欢迎查看更多与《为PostgreSQL讨说法:浅析Uber切换MySQL》相关教程,学精学透。编程之家PHP学院为您提供精彩教程。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读