NestJS+Prisma+PostgreSQL生产环境数据库恢复模式报错求助
解决PostgreSQL处于恢复模式导致Prisma查询失败的问题
错误本质
日志中的FATAL: the database system is in recovery mode说明你的PostgreSQL实例正处于恢复状态,无法正常处理查询请求。这种情况通常由数据库崩溃、主从同步异常、资源不足或磁盘问题引发。
排查与解决步骤
1. 检查PostgreSQL容器状态与日志
- 查看数据库容器的详细日志,定位恢复触发原因:
docker logs <你的PostgreSQL容器名或ID> - 检查容器是否频繁重启:
日志中可能会出现崩溃报错、磁盘空间不足或WAL日志异常等信息。docker ps -a
2. 确认数据库连接目标
- 如果是主从集群部署,确保应用连接的是主库:从库在同步主库数据时会进入recovery模式,仅支持只读操作(部分场景下甚至只读也受限),若误连从库会导致查询失败。
- 核对Prisma配置文件中的
DATABASE_URL,确认主机地址、端口指向正确的数据库实例。
3. 修复单实例数据库的恢复状态
- 进入PostgreSQL容器,检查恢复进度:
查看docker exec -it <postgres-container-name> pg_controldata /var/lib/postgresql/dataLatest checkpoint location和Recovery target location判断恢复是否在正常推进。 - 若恢复卡住或失败,优先检查磁盘空间:
磁盘满会导致数据库崩溃,清理空间后重启容器;若WAL日志损坏,需从最近的备份恢复数据库。docker exec <postgres-container-name> df -h
4. 优化Docker部署配置
- 给PostgreSQL容器分配足够的内存和CPU:资源不足会导致数据库频繁崩溃触发恢复,可在
docker-compose.yml中添加资源限制:services: postgres: image: postgres:15 resources: limits: memory: 2G cpus: '1.5' - 确保数据卷权限正确:PostgreSQL进程需要读写权限,主机挂载目录需设置为
postgres用户(UID=999):chown -R 999:999 /主机路径/postgres-data - 调整Prisma连接池参数:在
schema.prisma中设置合理的连接数,避免连接池耗尽压垮数据库:datasource db { provider = "postgresql" url = env("DATABASE_URL") shadowDatabaseUrl = env("SHADOW_DATABASE_URL") pool_size = 10 # 根据实例资源调整,默认是5 }
5. 代码层面添加容错重试
在Prisma查询处添加重试逻辑,避免数据库短暂恢复时直接返回错误给用户:
// wallpaper.menu.repository.ts async list(sortOptions?: any[]) { const newSortOptions = sortOptions ? [{ orderBy: 'page', order: 'asc' }, ...sortOptions] : [{ orderBy: 'page', order: 'asc' }]; const maxRetries = 3; let currentRetry = 0; while (currentRetry < maxRetries) { try { return await this.menuRepository.findMany({ orderBy: newSortOptions }); } catch (error) { currentRetry++; // 仅针对recovery模式错误进行重试 if (error.message.includes('the database system is in recovery mode') && currentRetry < maxRetries) { await new Promise(resolve => setTimeout(resolve, 1000)); // 间隔1秒重试 continue; } throw error; } } throw new Error('数据库处于恢复模式,重试次数耗尽'); }
内容的提问来源于stack exchange,提问作者Tuấn Vũ Quý
相关产品推荐
相关产品推荐

