Skip to content

MySQL 用户迁移到 PostgreSQL 指南 ​

从 MySQL 转到 PG,最需要知道的差异。

1. 语法差异速查 ​

MySQLPostgreSQL说明
AUTO_INCREMENTSERIAL / BIGSERIAL / GENERATED ALWAYS AS IDENTITYPG 推荐用 IDENTITY
IFNULL(a, b)COALESCE(a, b)PG 不支持 IFNULL
GROUP_CONCAT(...)STRING_AGG(...)语法不同
LIMIT 10 OFFSET 20相同一致
SHOW DATABASES\l 或 SELECT datname FROM pg_databaseCLI 不同
SHOW TABLES\dt 或 SELECT relname FROM pg_class WHERE relkind='r'CLI 不同
DESCRIBE table\d tableCLI 不同
NOW()NOW() / CURRENT_TIMESTAMP一致
ENGINE=InnoDB不需要PG 只有一种存储引擎
`backtick`"doublequote"标识符引用不同

2. 事务隔离级别 ​

sql
-- MySQL 默认:REPEATABLE READ
-- PostgreSQL 默认:READ COMMITTED

-- 查看当前隔离级别
SHOW transaction_isolation;

-- 设置隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

PG 的 READ COMMITTED 行为与 MySQL 的 RR 不同:每次 SELECT 看到的是该语句开始时的最新已提交数据,而不是事务开始时的快照。

3. MVCC 差异 ​

sql
-- MySQL:旧版本在 Undo Log,自动回收
-- PostgreSQL:旧版本在堆表中,需要 VACUUM

-- 查看 Dead Tuple
SELECT relname, n_live_tup, n_dead_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC;

4. JSONB 是 PG 的杀手级特性 ​

sql
-- MySQL JSON:文本存储,索引能力有限
-- PG JSONB:二进制存储,支持 GIN 索引

-- 创建 JSONB 列
CREATE TABLE products (id SERIAL, attrs JSONB);

-- 建 GIN 索引
CREATE INDEX idx_attrs ON products USING GIN (attrs);

-- 查询(MySQL 做不到的高效查询)
SELECT * FROM products WHERE attrs @> '{"brand": "Apple"}';

5. 窗口函数 ​

sql
-- MySQL 8.0+ 才支持,PG 支持更完整
SELECT name, department, salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn,
    LAG(salary) OVER (PARTITION BY department ORDER BY salary) AS prev_salary
FROM employees;

6. 连接与认证 ​

bash
# MySQL
mysql -u root -p -h localhost mydb

# PostgreSQL
psql -U postgres -h localhost -d mydb
# 或
PGPASSWORD=xxx psql -U postgres -h localhost -d mydb

7. 常见陷阱 ​

陷阱说明
字符串用单引号PG 的标识符用双引号,字符串用单引号,与 MySQL 相同但更严格
BOOLEAN 值PG 用 true/false,不是 1/0
日期格式PG 推荐 ISO 8601(2024-01-15),不支持 MySQL 的自由格式
隐式类型转换PG 不做隐式转换,WHERE id = '123' 会报错(id 是 INT 时)
GROUP BYPG 严格要求 SELECT 中的非聚合列都在 GROUP BY 中
TRUNCATE 重启序列PG 的 TRUNCATE 不会重置 SERIAL 序列,需要 TRUNCATE ... RESTART IDENTITY

8. ORM 适配 ​

yaml
# Spring Boot JPA 配置
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    driver-class-name: org.postgresql.Driver
  jpa:
    database-platform: org.hibernate.dialect.PostgreSQLDialect
yaml
# MyBatis 无需特殊配置,方言自动识别
# 注意:MyBatis-Plus 的自增策略需要调整
# MySQL: @TableId(type = IdType.AUTO)
# PostgreSQL: @TableId(type = IdType.AUTO) 或使用序列

Released under the MIT License.