外观
PostgreSQL 常见错误码解析
错误码概述
PostgreSQL使用标准的SQL错误码,每个错误码由5个字符组成,分为两个部分:
- 前两个字符表示错误类别
- 后三个字符表示具体错误
错误码以"XXYYY"格式表示,例如"28000"表示认证失败。
错误码分类
1. 类00 — 成功完成
- 00000:成功完成
2. 类01 — 警告
- 01000:警告
- 0100C:动态结果集返回
- 01008:隐含类型转换
- 01003:空值消除
3. 类02 — 无数据
- 02000:无数据
- 02001:未找到行
4. 类03 — 语句完成
- 03000:语句完成
5. 类08 — 连接异常
- 08000:连接异常
- 08001:无法连接到服务器
- 08003:连接不存在
- 08004:服务器拒绝连接
- 08006:连接失败
- 08007:事务解析失败
- 0800B:连接已关闭
6. 类09 — 触发器异常
- 09000:触发器异常
7. 类0A — 特性不支持
- 0A000:特性不支持
8. 类0B — 无效事务终止
- 0B000:无效事务终止
9. 类0F — 无效凭证
- 0F000:无效凭证
10. 类0L — 无效授权规范
- 0L000:无效授权规范
11. 类0P — 无效架构名称
- 0P000:无效架构名称
12. 类20 — 无效事务状态
- 20000:无效事务状态
- 20001:无效事务终止
- 20002:无效事务状态
13. 类21 — 无效游标状态
- 21000:无效游标状态
14. 类22 — 数据异常
- 22000:数据异常
- 22001:字符串数据右截断
- 22002:空值违反非空约束
- 22003:数值超出范围
- 22004:空值不允许
- 22005:错误的参数类型
- 22007:无效的日期/时间格式
- 22008:日期/时间溢出
- 22009:无效的时区位移值
- 2200B:除零错误
- 2200D:无效的编码序列
- 2200E:字符串长度不匹配
- 2200F:无效的字符值
- 22012:除零错误
- 22015:间隔字段溢出
- 22018:无效的字符值
- 22019:无效的转义字符
- 22025:无效的正则表达式
- 22026:字符串长度不匹配
- 22P01:无效的文本表示
- 22P02:无效的二进制表示
- 22P03:无效的JSON文本
- 22P04:无效的XML文档
- 22P05:无效的UUID
- 22P06:无效的数组下标
- 22P07:无效的记录下标
15. 类23 — 约束违反
- 23000:完整性约束违反
- 23001:限制违反
- 23502:非空约束违反
- 23503:外键约束违反
- 23505:唯一约束违反
- 23506:检查约束违反
- 23514:排除约束违反
16. 类24 — 无效游标状态
- 24000:无效游标状态
17. 类25 — 无效事务状态
- 25000:无效事务状态
- 25001:活动SQL事务中不允许操作
- 25002:事务中不允许连接操作
- 25003:无效的事务终止
- 25004:事务状态无效
- 25005:事务已提交
- 25006:事务已回滚
- 25007:只读SQL事务
- 25008:事务内的原子性违反
18. 类26 — 无效SQL语句名
- 26000:无效SQL语句名
19. 类27 — 触发器相关错误
- 27000:触发器相关错误
20. 类28 — 无效授权规范
- 28000:无效授权规范
21. 类2B — 依赖特权撤销
- 2B000:依赖特权撤销
22. 类2D — 无效事务终止
- 2D000:无效事务终止
23. 类2F — SQL函数异常
- 2F000:SQL函数异常
24. 类34 — 无效游标名
- 34000:无效游标名
25. 类38 — 外部例程异常
- 38000:外部例程异常
26. 类39 — 外部例程调用异常
- 39000:外部例程调用异常
27. 类3B — 保存点异常
- 3B000:保存点异常
28. 类3D — 无效目录名
- 3D000:无效目录名
29. 类3F — 无效模式名
- 3F000:无效模式名
30. 类40 — 事务回滚
- 40000:事务回滚
- 40002:事务完整性约束违反
- 40003:语句完成未知
- 40P01:死锁检测到
31. 类42 — 语法或访问规则错误
- 42000:语法错误或访问规则违反
- 42001:语法错误
- 42002:表不存在
- 42003:列不存在
- 42004:字段定义重复
- 42005:对象已存在
- 42008:WITH子句冲突
- 42010:无效的表名
- 42011:无效的列名
- 42012:无效的模式名
- 42014:无效的参数名
- 42015:函数重定义冲突
- 42016:约束重定义冲突
- 42017:索引重定义冲突
- 42018:表重定义冲突
- 42019:数据类型重定义冲突
- 42020:模式重定义冲突
- 42021:视图重定义冲突
- 42022:序列重定义冲突
- 42023:规则重定义冲突
- 42024:触发器重定义冲突
- 42025:过程重定义冲突
- 42026:类型重定义冲突
- 42P01:表或视图不存在
- 42P02:字段不存在
- 42P03:未定义的函数
- 42P04:数据库已存在
- 42P05:数据库不存在
- 42P06:模式已存在
- 42P07:模式不存在
- 42P08:关系已存在
- 42P09:关系不存在
- 42P10:数据类型已存在
- 42P11:数据类型不存在
- 42P12:操作符类已存在
- 42P13:操作符类不存在
- 42P14:操作符族已存在
- 42P15:操作符族不存在
- 42P16:聚合函数已存在
- 42P17:聚合函数不存在
- 42P18:排序规则已存在
- 42P19:排序规则不存在
- 42P20:无效的列引用
- 42P21:无效的列定义
- 42P22:无效的表引用
32. 类44 — 内部错误
- 44000:内部错误
33. 类53 — insufficient_resources
- 53000:资源不足
- 53100:磁盘空间不足
- 53200:内存不足
- 53300:达到连接限制
- 53400:配置限制超出
34. 类54 — 程序限制
- 54000:程序限制
- 54001:语句太长
- 54011:列太多
- 54023:太多参数
- 54024:太多RETURN语句
35. 类55 — 对象状态
- 55000:对象状态无效
- 55001:对象正在使用中
- 55006:对象未处于有效状态
36. 类57 — 运算符异常
- 57000:运算符异常
- 57014:查询超时
- 57P01:管理员关闭了连接
- 57P02:系统正在关闭
- 57P03:取消请求
- 57P04:连接丢失
- 57P05:致命错误
37. 类58 — 系统错误
- 58000:系统错误
- 58030:I/O错误
- 58P01:未定义的文件
- 58P02:重复文件
38. 类72 — 快照太旧
- 72000:快照太旧
39. 类F0 — 配置文件错误
- F0000:配置文件错误
40. 类HV — 外部表错误
- HV000:外部表错误
- HV005:外部表未找到
41. 类P0 — PL/pgSQL错误
- P0000:PL/pgSQL错误
- P0001:RAISE异常
- P0002:无数据返回
- P0003:太多行返回
42. 类XX — 内部错误
- XX000:内部错误
- XX001:数据损坏
- XX002:索引损坏
常见错误码解析与解决方案
1. 连接错误 (08000系列)
08001: 无法连接到服务器
原因:
- 服务器未运行
- 网络连接问题
- 防火墙阻止连接
- 端口配置错误
解决方案:
bash
# 检查服务器状态
systemctl status postgresql-14
# 检查端口是否监听
netstat -tuln | grep 5432
ss -tuln | grep 5432
# 检查防火墙设置
iptables -L -n
firewall-cmd --list-ports
# 测试网络连接
telnet hostname 5432
ping hostname08004: 服务器拒绝连接
原因:
- 客户端IP不在允许列表中
- 用户名或密码错误
- 数据库不存在
解决方案:
bash
# 检查pg_hba.conf配置
cat /var/lib/postgresql/14/main/pg_hba.conf
# 检查用户名和数据库是否存在
psql -U postgres -c "SELECT usename FROM pg_user;"
psql -U postgres -c "SELECT datname FROM pg_database;"2. 数据异常 (22000系列)
22P02: 无效的二进制表示
原因:
- 尝试将无效的二进制数据转换为某种数据类型
- 数据损坏
解决方案:
sql
-- 检查数据完整性
SELECT * FROM table_name WHERE column_name::bytea IS NULL;
-- 修复损坏的数据
UPDATE table_name SET column_name = NULL WHERE column_name::bytea IS NULL;22003: 数值超出范围
原因:
- 插入的值超过了列定义的数据类型范围
- 计算结果溢出
解决方案:
sql
-- 检查列的数据类型和范围
SELECT column_name, data_type, character_maximum_length, numeric_precision, numeric_scale
FROM information_schema.columns
WHERE table_name = 'table_name';
-- 调整数据类型或值
ALTER TABLE table_name ALTER COLUMN column_name TYPE bigint;3. 约束违反 (23000系列)
23502: 非空约束违反
原因:
- 尝试向非空列插入NULL值
- 列定义为NOT NULL,但插入操作未提供值
解决方案:
sql
-- 检查列的约束
SELECT column_name, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = 'table_name';
-- 修复插入语句,提供非空值
INSERT INTO table_name (column1, column2) VALUES (value1, value2);
-- 或修改列允许NULL
ALTER TABLE table_name ALTER COLUMN column_name DROP NOT NULL;23503: 外键约束违反
原因:
- 尝试插入的外键值在引用表中不存在
- 引用表中的记录被删除
解决方案:
sql
-- 检查外键约束
SELECT conname, conrelid::regclass, confrelid::regclass
FROM pg_constraint
WHERE contype = 'f' AND conrelid::regclass = 'table_name'::regclass;
-- 检查引用表中是否存在对应记录
SELECT * FROM referenced_table WHERE id = foreign_key_value;
-- 修复外键值或添加对应记录
INSERT INTO referenced_table (id, ...) VALUES (foreign_key_value, ...);23505: 唯一约束违反
原因:
- 尝试插入的记录违反了唯一约束
- 表中已存在相同值的记录
解决方案:
sql
-- 检查唯一约束
SELECT conname, conrelid::regclass, conkey::regclass[]
FROM pg_constraint
WHERE contype = 'u' AND conrelid::regclass = 'table_name'::regclass;
-- 查找重复记录
SELECT column_name, COUNT(*)
FROM table_name
GROUP BY column_name
HAVING COUNT(*) > 1;
-- 修复重复记录
DELETE FROM table_name WHERE id NOT IN (SELECT MIN(id) FROM table_name GROUP BY column_name);4. 语法或访问规则错误 (42000系列)
42P01: 表或视图不存在
原因:
- 尝试访问不存在的表或视图
- 拼写错误
- 模式名称错误
- 权限不足
解决方案:
sql
-- 检查表是否存在
SELECT * FROM pg_tables WHERE tablename = 'table_name';
-- 检查视图是否存在
SELECT * FROM pg_views WHERE viewname = 'view_name';
-- 检查当前模式
SHOW search_path;
-- 检查用户权限
SELECT has_table_privilege('username', 'table_name', 'SELECT');42P02: 字段不存在
原因:
- 尝试访问不存在的列
- 拼写错误
- 列名大小写问题
解决方案:
sql
-- 检查表的列
SELECT column_name FROM information_schema.columns WHERE table_name = 'table_name';
-- 注意PostgreSQL对大小写敏感,使用双引号引用大小写混合的列名
SELECT "Column_Name" FROM table_name;5. 事务回滚 (40000系列)
40P01: 死锁检测到
原因:
- 两个或多个事务相互等待对方释放锁
- 长时间运行的事务
- 锁升级导致
解决方案:
sql
-- 查看当前锁等待
SELECT * FROM pg_locks WHERE granted = false;
-- 查看锁等待链
WITH RECURSIVE lock_chain AS (
SELECT l1.pid AS waiting_pid, l2.pid AS blocking_pid
FROM pg_locks l1
JOIN pg_locks l2 ON l1.locktype = l2.locktype AND l1.database = l2.database AND l1.relation = l2.relation
WHERE l1.granted = false AND l2.granted = true
)
SELECT * FROM lock_chain;
-- 终止阻塞事务
SELECT pg_terminate_backend(pid);
-- 优化事务,减少锁定时间
-- 1. 保持事务短小
-- 2. 按相同顺序访问表
-- 3. 使用行级锁而非表级锁
-- 4. 避免长时间运行的SELECT FOR UPDATE6. 资源不足 (53000系列)
53200: 内存不足
原因:
- 内存配置不足
- 大量并发连接
- 复杂查询消耗过多内存
解决方案:
sql
-- 检查当前内存使用情况
SELECT * FROM pg_stat_sys_memory; -- PostgreSQL 14+
-- 检查连接数
SELECT COUNT(*) FROM pg_stat_activity;
-- 调整内存相关参数
ALTER SYSTEM SET shared_buffers = '4GB';
ALTER SYSTEM SET work_mem = '16MB';
ALTER SYSTEM SET maintenance_work_mem = '256MB';
SELECT pg_reload_conf();
-- 优化查询,减少内存使用
EXPLAIN ANALYZE SELECT * FROM large_table WHERE complex_condition;
CREATE INDEX idx_large_table_column ON large_table(column);53100: 磁盘空间不足
原因:
- 数据文件增长过快
- WAL日志未及时清理
- 临时文件占用过多空间
解决方案:
bash
# 检查磁盘空间
df -h
# 检查数据目录大小
du -sh /var/lib/postgresql/14/main
# 检查WAL目录大小
du -sh /var/lib/postgresql/14/main/pg_wal
# 清理WAL日志(如果复制正常)
# 确保wal_keep_size或archive_command配置正确
# 清理临时文件
rm -rf /var/lib/postgresql/14/main/pg_temp*/*
# 分析表并回收空间
VACUUM ANALYZE VERBOSE table_name;
VACUUM FULL VERBOSE table_name; # 注意:会锁表7. 内部错误 (XX000系列)
XX001: 数据损坏
原因:
- 硬件故障
- 软件错误
- 操作系统崩溃
解决方案:
bash
# 检查数据完整性
pg_controldata /var/lib/postgresql/14/main
# 运行数据库检查
pg_verifybackup /path/to/backup
# 使用pg_resetwal修复(谨慎使用)
pg_resetwal -D /var/lib/postgresql/14/main -f
# 从备份恢复
pg_basebackup -D /var/lib/postgresql/14/main -c fast -Fp -Xs -v -P -U replication错误码分析工具
1. psql命令
bash
# 查看错误码和消息
psql -U postgres -c "SELECT * FROM pg_error_codes;"
# 按类别筛选
psql -U postgres -c "SELECT * FROM pg_error_codes WHERE code LIKE '22%';"2. pgAdmin
pgAdmin提供了图形化的错误码查询功能,可以在"工具"菜单中找到"错误码查找器"。
3. 在线资源
不同PostgreSQL版本的错误码差异
PostgreSQL 9.x
- 错误码较少
- 部分错误码描述不够详细
- 缺少一些现代数据类型的错误码
PostgreSQL 10+
- 增加了更多错误码
- 增强了错误码描述
- 支持更多数据类型的错误码
PostgreSQL 12+
- 增强了JSON相关错误码
- 增加了XML相关错误码
- 改进了错误信息的可读性
PostgreSQL 14+
- 增强了系统资源相关错误码
- 增加了更多的WAL相关错误码
- 改进了错误定位的准确性
错误处理最佳实践
1. 日志配置
ini
# 配置详细的错误日志
log_min_messages = warning
log_min_error_statement = error
log_error_verbosity = verbose
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '2. 应用端错误处理
示例(Python):
python
import psycopg2
from psycopg2 import OperationalError, IntegrityError
try:
conn = psycopg2.connect(
host="hostname",
database="database",
user="username",
password="password"
)
cur = conn.cursor()
cur.execute("SELECT * FROM table_name")
rows = cur.fetchall()
except OperationalError as e:
print(f"连接错误: {e}")
except IntegrityError as e:
print(f"完整性约束错误: {e}")
conn.rollback()
except Exception as e:
print(f"其他错误: {e}")
conn.rollback()
finally:
if conn:
conn.close()3. 监控和告警
- 设置监控工具(Prometheus + Grafana)监控错误率
- 配置告警规则,当错误率超过阈值时发送告警
- 定期分析错误日志,识别频繁出现的错误
4. 定期维护
- 定期运行
VACUUM ANALYZE - 检查数据库完整性
- 监控磁盘空间和内存使用
- 保持PostgreSQL版本更新,获取最新的错误修复
总结
PostgreSQL错误码提供了详细的错误信息,帮助DBA快速定位和解决问题。了解常见错误码的含义和解决方案,可以提高故障处理的效率。通过合理的日志配置、应用端错误处理、监控告警和定期维护,可以减少错误的发生,提高数据库的可靠性和稳定性。
