先说背景。我们上家公司是做电商中台的,用了五年 MySQL 5.7,后来因为业务量上来,订单表每天新增几十万行,加上团队里有个高P特别推崇 PostgreSQL,就咬牙启动了从 MySQL 迁到 PostgreSQL 15 的大工程。我作为运维负责人,全程参与了迁移、压测和上线,前前后后折腾了大半年。说实话,网上那些对比文章大多停留在语法差异和‘谁快谁慢’的层面,真正到生产环境里才会发现,选型这事根本不是性能参数能决定的。
第一个让我心态崩掉的是锁机制。MySQL 的 InnoDB 默认锁等待超时是 50 秒,我们线上一直没改过,平时偶尔死锁,应用重试一下也就过去了。但 PostgreSQL 的 lock_timeout 默认是 0,也就是无限等待,结果迁移后第一周就出事了。我们的库存扣减逻辑里有个先查后更新的操作,两个事务同时抢同一批 SKU,在 MySQL 下会很快报死锁让一方回滚,但 Postgres 下两个事务都拿到了快照,然后互相等对方提交,等到应用层超时也没解开。后来我们不得不在所有涉及热点行更新的事务里显式加上 lock_timeout 和 advisory lock,还把隔离级别从 Read Committed 降到了 Repeatable Read 的某些场景才缓解。所以别光看 TPC-C 分数,锁行为差一点就是事故和救火的区别。
再说说扩展和运维维度。MySQL 的异步复制是我们早已习惯的,主从延迟在高峰期能到 2 秒,但我们读写分离分的很细,基本能忍。Postgres 的逻辑复制虽然更灵活,但物理复制只有一种流复制,而且受单机 WAL 产生的瓶颈影响很大。我们压测时模拟了 8 核 16G 的实例,Postgres 的流复制在主库写入 TPS 到 5000 左右时,备库延迟就开始飘,而 MySQL 同配置下能扛到 8000 TPS 才接近极限。另外备份恢复,MySQL 用 Percona XtraBackup 备份 200G 的数据大概是 40 分钟,恢复到新实例也差不多;Postgres 用 pg_basebackup 加上 WAL 归档,备份虽然快一些,但恢复时需要重放 WAL,花了快一个半小时。这些都是实打实的数字,选型前最好拿自己的数据量测一遍,别信网上那套。
还有团队和工具链这件事。我们团队五个人,三个对 MySQL 熟到能看 binlog 分析事务,对 Postgres 基本是现学。迁移后第一个月,日常的慢查询优化、索引重建、vacuum 调优全都要我来兜底,因为 DBA 之前只考过 MySQL 证书。还有那些内部平台,监控告警、SQL 审核、数据脱敏,统统要适配新数据库。有个同事写了个关联四张表的复杂查询,在 MySQL 里跑 1.2 秒,到了 Postgres 因为统计信息不准,走了嵌套循环,直接干到 15 秒,后来得手动 set enable_nestloop=off 才救回来。这让我意识到,数据库切换不光是技术选型,更是团队认知的迁移,代价可能比想象中大一个数量级。
最后我说说自己的结论。如果你的业务是典型互联网海量读多写少,团队长期用 MySQL,那别轻易为了某个‘高级功能’切到 PostgreSQL。Postgres 确实在 JSONB、多表复杂查询、扩展类型上更强大,但它更适合数据准确性要求极高、写并发不高、且团队愿意花时间深入 PostgreSQL 的场合。我做了一个迁移评估清单,包括锁等待超时、复制延迟、备份恢复时间、团队熟悉度、工具链兼容,还有一条最重要的——把业务里最高频的十种 SQL 模式跑一遍,记录行为而不是只测个 select 1。选型不是比谁跑分高,而是比谁的数据生命周期管理能力和你团队的能力半径匹配。现在我的电脑里还留着当时压测的完整报告和事故复盘,每次有人问我该选哪个,我就把这堆文件发过去,然后补一句:你们敢不敢把 lock_timeout 改成 0 试试?