ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PostgreSQL功能更强,为何生产环境仍被MySQL主导?五本账说清楚

PostgreSQL功能更强,为何生产环境仍被MySQL主导?五本账说清楚 每隔一段时间技术群里就会冒出一个经典灵魂拷问PostgreSQL文档更严谨、SQL标准兼容性更好、JSONB处理半结构化数据的能力比MySQL强了不止一档、索引类型多到选型困难为什么很多公司还是抱着MySQL不放这个问题我这些年起码被问过二十次。我自己两套数据库都在生产环境深度用过不打算偏袒哪一边。先把结论摆出来PG那些优势我一条都不否认甚至我自己的一些分析类项目就用PG。但MySQL到今天依然占据大量生产环境真不是因为DBA们看不到PG的好而是因为选型时候真正较量的不是功能列表而是安装门槛、人才供给、周边生态、团队惯性、迁移风险这五本账。这篇文章就把这五本账摊开来算顺便把我在实操里踩过的坑也一并倒出来。1. 先把背景说清楚PG 和 MySQL 到底差在哪一层1.1 两套数据库的真实定位PostgreSQL的官方定位是“世界上最先进的开源关系型数据库”这口号不是白喊的。它从1986年的伯克利POSTGRES项目一路演变过来三十年多年沉淀功能像瑞士军刀一样齐全复杂查询、窗口函数、递归CTE、物化视图、PostGIS地理空间扩展、JSONB、自定义类型几乎你能想到的数据库能力它都有。MySQL的基因完全不同。它早期诞生时追求的是“轻量、快速、够用”黄金时代和Web应用、PHP、LAMP架构几乎同步成长。InnoDB引擎在事务、崩溃恢复上做了大量打磨但它整体设计思路就是服务OLTP没打算把什么功能都塞进去。两句话总结PG是功能全面的数据库全家桶什么都能干、干得漂亮MySQL是一把顺手的螺丝刀拧普通螺丝又快又稳。这种基因差异直接决定了今天的分工。PG适合复杂场景、数据仓库混合负载、空间数据、JSON数据混合业务MySQL适合纯纯的在线事务处理简单直接出了常见问题一搜就有答案。1.2 为什么 PG 这两年存在感这么高PG存在感飙升有几个很扎实的原因。一是版本迭代明显提速。15、16、17接连发布每代都有实打实的性能提升尤其并行查询、vacuum调度、逻辑复制这些方面都是从“能用”往“好用”走。我自己的体会是PG 16之后默认配置下的并发表现已经比前几个大版本稳太多了。二是一大批Oracle存量项目开始往开源数据库迁而PG在SQL标准、约束、权限模型、窗口函数这些层面的行为是最接近Oracle习惯的。国内很多金融、政企项目现在做Oracle替代第一反应就是PG。三是社区数据摆在那里。Stack Overflow每年的开发者调查里PG在“计划使用率/频繁使用率”上一直排在开源数据库前列。热词里的“postgresql 16便携版”、“centos7.9下安装postgresql”、“docker安装postgresql”也能看出来越来越多个人开发者和运维在动手尝试PG。但走到真实业务里情况就不一样了。招聘网站上MySQL岗位的数量、云数据库控制台里的默认选项、教程视频的存量、各公司线上系统的分布MySQL依旧遥遥领先。这就引出了整篇文章的核心矛盾功能更全不等于综合成本更低。2. 先承认PG 的功能优势确实是实打实的2.1 SQL标准与查询能力的代差我在MySQL里写复杂报表逻辑时经常要借助临时表、多次子查询嵌套来绕路但在PG里同样的需求往往一条SQL就能搞定。举一个很常见的例子一张商品分类表category_id和parent_id构成树形结构要查出某个分类下所有层级的子分类。MySQL 8.0以前的版本没有递归CTE只能写存储过程或者业务代码一层层循环PG从8.4开始就原生支持WITH RECURSIVE一个递归查询干净利落。MySQL 8.0虽然也补上了CTE支持但如果你接手的是老项目、跑在5.7上那就只能继续绕路。窗口函数也是同样的道理。排名、分组内TopN、移动平均这类分析需求PG语法写起来非常自然。MySQL 8.0之后窗口函数慢慢齐了但遇到FILTER子句、更复杂的窗口定义MySQL的支持程度和PG还有差距。还有CHECK约束、正则表达式、部分索引、表达式索引、支持NULLS FIRST/LAST的排序等等这些看着不起眼实际写业务时非常顺手。PG对SQL标准的执念带来的直接好处是你的SQL技能迁移成本低熟悉标准SQL写法的开发者在PG里基本无障碍。2.2 数据类型与扩展生态这一块是PG最让MySQL用户眼馋的地方。JSONB可以算PG近些年最亮眼的功能之一。它把JSON数据做二进制存储支持GIN索引可以在JSON字段内部直接走索引检索还能用各种JSON运算符做条件过滤。我做过一个配置中心项目大量半结构化配置直接丢JSONB查询性能和使用体验都比原来MySQL里存JSON文本高一个档次。MySQL 8.0也有JSON类型能做索引了但整体能力和JSONB的灵活性、丰富的操作符、以及和关系表数据混合使用的顺手程度没法比。PG的数组类型、范围类型、枚举类型、自定义复合类型让业务建模多了很多可能性。比如排课系统里存一个老师一周可用时间段的数组在PG里就是一个原生类型在MySQL里只能拆表或者存字符串再清洗。更恐怖的是PostGIS。空间地理查询方面它几乎是开源事实标准。如果你要处理经纬度、行政区划、轨迹点、路径规划这些PGPostGIS是成熟方案MySQL的Spatial能力相对薄弱复杂拓扑查询基本没法比。PG还有一个MySQL没有的“外挂机制”CREATE EXTENSION。uuid支持、模糊匹配pg_trgm、加密函数pgcrypto、键值对hstore一个扩展命令搞定不用改内核。2.3 事务、并发与可靠性设计PG的MVCC实现和MySQL InnoDB不一样它把版本信息直接存在数据行的系统列里用vacuum机制清理旧版本没有独立的undo日志。这套设计在“读多写少大量并发读”的场景下非常稳健而且PG的隔离级别支持在可重复读下通过更严格的方式避免幻读。MySQL在RR级别靠next-key lock解决幻读问题行锁开销和死锁概率会高一些。逻辑复制方面PG这些年的原生逻辑复制已经相当成熟支持基于行的增量同步、双向复制、冲突检测而且不需要第三方工具。MySQL也有binlog-based复制成熟度毋庸置疑但PG从早期只能靠触发器和外部脚本玩逻辑复制到现在原生逻辑复制做得这么顺手进步确实非常明显。物理流复制方面PG支持同步/异步流复制、级联复制、时间点恢复PITR搭建高可用集群的手段很丰富。你如果做金融项目、对数据一致性要求苛刻PG在这块的严谨性会让你很安心。3. MySQL 的护城河它赢在“综合成本最低”3.1 安装、配置、上手门槛这是我职业生涯里最有体感的部分。MySQL的官网提供Windows一键Installer下载、下一步、下一步填个密码就能跑起来。Linux下有yum/apt官方仓库apt install mysql-server起服务、改密码、完事。就连zip解压版mysqld --initialize之后net start mysql也能用。网上保姆级教程多到爆炸“mysql安装教程”随便一搜就是几百篇。PG在Windows下的体验就陡峭多了。很多朋友下载了“postgresql windows 安装版”第4步选择安装目录时如果不小心勾了中文路径后面服务大概率起不来有的装完以后连psql都进不去默认的postgres用户密码输错一次就懵了。更常见的是装完以后服务根本没起来定位问题要去翻postgresql.conf、pg_hba.conf、看Windows事件日志这对刚接触PG的人来说是劝退级别。就算装好了PG的默认参数也需要一定的底子。shared_buffers、work_mem、maintenance_work_mem、max_wal_size这些参数搭配不好高并发下PG的表现会打折扣。MySQL 8.0默认配置在大多数中小业务上开箱即用掉坑概率低很多。我见过太多“PG装了但一直没敢上生产”的真实案例原因不是PG不好而是团队对它不熟调优不会调出了问题也不知道去哪里查。3.2 人才储备出问题时谁能帮你这是我们选型时经常被忽略、但实际杀伤力最大的一项。一个只懂MySQL的DBA处理日常问题、主从延迟、deadlock、慢查询优化可能得心应手但切到PG以后vacuum、膨胀、锁等待、参数调优、逻辑复制冲突全部要重新学。招聘市场上熟练的PG DBA数量远比MySQL DBA稀缺价格也更高。中小团队更是如此。公司没有专职DBA应用开发顺便管库他们最熟悉的知识来源就是搜索引擎里那些MySQL排错文章。一旦线上PG出了诡异问题能当场接得住手的人可能整个公司都找不到。这不是PG技术本身的错是生态里配套的人力沉淀还不够。3.3 复制架构与中间件生态方案确实成熟MySQL的主从复制配置我在线上做过的步骤非常简单开binlog、配server-id、设个复制用户、change master to或者source to一条链路就通了。主从切换、半同步、GTID模式这些方案在中文互联网上被讨论过千百遍任何一个小团队踩坑以后都能搜到对应解决方案。MySQL周边的中间件生态也成熟得可怕。MyCat、ShardingSphere、Atlas、ProxySQL读写分离、分库分表、代理治理随便一个都有大量生产案例和排错文章。ORM框架层面MyBatis、Hibernate、Django ORM、Rails ActiveRecord对MySQL的适配默认得不能再默认很多框架你不做任何配置就默认往MySQL方向走。PG这边不是没有方案pgpool-II、Patroni、Citus这些也都是好东西但中文社区的实战分享、踩坑帖子数量比MySQL少了几个量级。我并不是说PG生态不行而是说当你的团队只有30分钟解决一个生产问题的时间时MySQL方案的“答案密度”更高。3.4 云厂商和周边工具的默认支持国内云厂商的RDS产品线里MySQL往往是“标准答案”。一键创建实例、自动备份、只读实例、监控告警、参数模板整套东西打磨得极其顺手。公司上了云数据库MySQL以后DBA很多日常运维压力其实是云厂商扛掉的。周边工具也一样。Navicat很早就原生支持MySQLDataGrip、DBeaver对MySQL支持也很顺。但很多团队用的可能还是Navicat MySQL破解版、或者Navicat for MySQL专门版本这些工具切换去连PG虽然也能用但团队使用习惯、已有密钥、内部工具链都是现成的MySQL配套换成PG意味着整套开发链路里的工具都得换一遍。云上自动备份、只读实例、审计日志、甚至控制台里的慢查询分析对MySQL支持最完善。公司一旦把系统的存储底座定在云MySQL上想要换PG等于把运维链路从底层全部换掉这个成本绝大多数业务不会轻易有勇气去承担。4. 更现实的问题你的业务真的“配得上”PG 的高级功能吗4.1 九成业务的负载模型其实很简单我这些年看过太多项目了嘴上说要用PG是因为“以后可能有复杂分析需求”实际上跑起来以后全是简单的订单表增删改查、用户表登录验证、商品列表翻页。这些标准OLTP场景MySQL和PG执行效率没有本质差别甚至MySQL因为默认配置简单、团队熟练反而更省心。有个很扎心的事实很多团队嘴上欣赏PG的JSONB和窗口函数但真正写的SQL还是SELECT * FROM table WHERE status 1 ORDER BY id DESC LIMIT 20。这种业务选谁都不会错真正会让你错的是选了PG以后没人会运维。4.2 团队成员的学习曲线不能忽略新招一个MySQL开发入职当天就能上手写CRUD换成PG哪怕开发水平高也得先适应权限模型、理解vacuum是什么、搞明白extension怎么装、知道为什么有时候连接数不够用。这中间至少有2-4周的学习摩擦。在快速迭代的创业公司里时间就是生命线。团队里如果没有人对PG有实战经验那我倾向于建议不要在生产核心链路贸然换数据库。技术债可以慢慢还但上线前临时抓瞎的成本是实实在在的。4.3 一张表说清楚什么时候选谁我给自己和团队做选型时用下面这张决策参考表基本能把90%的场景覆盖住评估维度倾向MySQL倾向PostgreSQL业务复杂度标准OLTP、简单CRUD、常规报表复杂查询、OLAP混合负载、复杂权限数据结构特征固定表结构为主大量JSON半结构化、自定义类型、数组地理空间需求基本不涉及PostGIS是刚需团队经验全员熟悉MySQL没有专职DBA有PG生产经验或专职DBA上线节奏要快容器里一键起、教程最多有时间做参数调优和运维体系搭建高并发读写主从读写分离方案成熟高并发需要精细调优门槛更高生态对接ORM/中间件/云RDS默认支持需要扩展/自研能力更强这个表格不是用来做技术攀比的而是用来做成本评估的。团队里如果连问题都搜不到答案再先进的功能也用不起来。5. 实操中的真实体验从安装到迁移的坑5.1 PG 最容易劝退新手的几个瞬间先说我个人和周围朋友在PG实战中踩过、且频率极高的坑。Windows下装了PG却起不来服务。最常见原因三个安装路径带中文data目录权限不足5432端口被占用。解决办法也不复杂重新安装时用纯英文路径安装后手动检查data目录权限用netstat -ano查端口占用。远程连接连不上。PG默认的pg_hba.conf只允许localhost你要远程连必须加一行类似host all all 0.0.0.0/0 scram-sha-256还要把postgresql.conf里的listen_addresses改成*。很多新手改了其中一个忘了另一个折腾半天连不上。这类问题在MySQL那边出现得少因为MySQL默认监听所有地址了上来就是改root密码。连接数不够用。PG默认max_connections只有100一个应用连接池稍微配大一点就直接报too many connections。MySQL默认151虽然也不算大但同样配置下普通应用遇到的概率更小而且PG每个后端进程占内存更多连接数提升对内存的压迫感更强。默认没有“create database”的习惯。新手连上PG以后习惯性输入SHOW DATABASES结果发现没有这条命令要用\l。这也算是历史习惯差异带来的小摩擦。还有一个典型场景下载了所谓“postgresql 16便携版”或者绿色解压版误以为解压就能用结果双击psql.exe直接闪退其实需要先跑initdb初始化data目录。PG的解压版本质上只是软件本体数据目录要自己初始化这个操作比MySQL的mysqld --initialize更隐晦因为错误提示不够友好。5.2 MySQL 也不是没有自己的坑平心而论MySQL这些年也有不少让运维脑溢血的瞬间。MySQL 8.0默认的认证插件是caching_sha2_password老版本Navicat连不上报错1251。解决办法是ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;这是几乎每个MySQL 8使用者都会遇到的第一课。JDBC连接MySQL时常见的“ssl连接错误”本质上是客户端和服务端SSL证书配置不一致。开发环境图省事连接串里加useSSLfalseallowPublicKeyRetrievaltrue问题立刻消失。但生产环境建议还是把SSL证书配好别省这个安全成本。Windows解压版MySQL没写my.ini就初始化的话非常容易用着用着突然起不来因为没有基础配置datadir和端口可能都被默认到了C盘深处。我踩过一次大坑后现在解压版一定先手动写好my.ini再mysqld --initialize-insecure。MySQL 5.7和8.0之间的排序规则迁移问题旧库用utf8mb4_general_ci新库默认utf8mb4_0900_ai_ci导入数据后所有ORDER BY排序结果可能都变了。迁移前务必将表统一排序规则。5.3 常见问题的避坑速查表问题现象常见场景快速处理方式1251认证错误Navicat连MySQL 8改认证插件为mysql_native_passwordJDBC连接报SSL错误Java连MySQL连接串加useSSLfalseallowPublicKeyRetrievaltruePG远程Connection refused应用不在本机改listen_addresses*同时改pg_hba.conf加对应权限PG连接数爆满连接池配置过大调大max_connections同时注意物理内存Windows PG服务无法启动安装或初始化问题路径纯英文、检查data目录权限、查端口占用MySQL解压版启动失败Windows免安装版手动创建my.ini再初始化数据目录utf8mb4排序结果变化从5.7迁移到8.0统一建表用utf8mb4_0900_ai_ci或旧_unicode_ciPG误以为无法修改字段结构变更不如MySQL方便PG的ALTER TABLE功能更强大但DDL锁表要注意窗口这些坑单独看都是小事但组合起来就能解释为什么很多团队“用起来顺手”的数据库不一定是最多亮点的那个。6. 我个人现在的选型原则6.1 什么情况我坚决上 PG项目里明确需要PostGIS的时候没有任何商量余地直接PG。JSON半结构化和关系数据混合比例高的时候我的第一选择也是PGJSONB在嵌套查询、索引过滤、字段动态追加这些场景下体验太舒服了。复杂的分析型查询、报表平台、数据仓库混合负载PG的窗口函数、CTE、物化视图能让开发效率整体上一个台阶。还有从Oracle迁过来的项目无论从SQL习惯还是功能覆盖度来说PG都是最平滑的着陆点。6.2 什么情况我继续用 MySQL标准Web后台、电商订单、内容管理系统、用户中心这种“建表、增删改查、主从读写分离”的模式下我毫不犹豫继续用MySQL。不是说PG不行而是这种业务形态下MySQL的顺手程度和生态答案密度实在太高团队里随便一个后端都能搞定。如果项目要快速上线、团队以MySQL经验为主、云上已经采购了MySQL RDS哪怕我内心知道PG某些方面更优秀我也会建议继续用MySQL推进业务。把熟悉的东西跑出稳定可靠的结果比追求“数据库先进”重要一百倍。6.3 最后分享一个小经验数据库选型不是一次技术崇拜而是一次成本管理。我踩过的坑足够说明选型真正应该看的是两张清单第一张是你业务未来三年的功能需求清单第二张是你团队今天现有的能力和精力清单。把两张清单对照起来看答案往往会自己浮出来。如果你想试PG又担心步子太大我给你一个渐进式思路挑一个非核心、非链路的分析型业务先迁上去跑两个迭代感受一下运维手感。慢慢你会发现PG的好用是真实的MySQL的顺手也是真实的。它们本来就是两种侧重点不同的工具非要分出谁彻底取代谁没有意义。把数据安全、备份恢复、监控告警这些基本功做扎实比你在两个数据库之间反复摇摆重要得多。
返回列表