应明确排除非事务表并禁用锁表:用–single-transaction配合–skip-lock-tables,–ignore-table排除myisam表,避免全局锁;大库导出需分段处理、大表单独导出并控制每条insert行数;必须校验pg_dump退出码和文件头合法性;rsync同步前须确保压缩完成且使用原子重命名。

mysqldump 备份时锁表导致业务卡顿怎么办
默认 mysqldump 对 InnoDB 表会加 READ LOCK,哪怕用了 --single-transaction,一旦遇到非事务表(比如 MyISAM)或显式锁表语句,整个 dump 过程仍可能阻塞写入。
真正安全的做法是:只对 InnoDB 表启用一致性快照,明确排除非事务引擎。
- 加
--single-transaction(必须搭配--skip-lock-tables,否则无效) - 用
--ignore-table=db.myisam_log排除非事务表,避免它触发全局锁 - 确认数据库未开启
autocommit=0或长事务,否则快照可能拉取到过旧数据 - 如果必须备份 MyISAM 表,改用
mysqlhotcopy(已弃用)或停写 +FLUSH TABLES WITH READ LOCK手动操作,不能混用
pg_dump 导出大库慢、内存爆掉怎么调
pg_dump 默认单连接、全量加载到内存再写文件,导出 50GB+ 数据时容易 OOM 或超时。关键不是“加参数”,而是拆解导出动作本身。
- 用
--section=pre-data/--section=data/--section=post-data分段导出,把 DDL 和数据分离,便于并行或分片处理 - 对大表单独用
--table=big_table --inserts配合--rows-per-insert=1000,避免单条 INSERT 过长触发 WAL 压力 - 禁用
--compress(客户端压缩),改用管道接gzip -1,节省内存且不影响传输效率 - 注意
work_mem在 dump 连接里不生效,别在postgresql.conf里盲目调高它来“优化 dump”
备份脚本里没校验 pg_dump 返回码就发邮件成功通知
很多脚本用 pg_dump ... > backup.sql 2>/dev/NULL 后直接 echo “success”,但 pg_dump 出错时仍可能生成空文件或截断文件,退出码却是 0 —— 因为重定向掩盖了 stderr,而某些错误(如权限不足读取 pg_largeobject)只报在 stderr。
- 永远用
set -e或显式检查$?,且不重定向 stderr 到/dev/null - 加
--no-unlogged-table-data避免因 unlogged 表不可读导致静默跳过 - 导出后立刻用
head -c 100 backup.sql | grep -q "PGDMP"确认文件头合法,再用wc -l看是否明显少于预期行数 - 不要依赖文件大小判断成败,空库和失败导出都可能产生 1KB 左右的文件
用 rsync 同步备份到远端时覆盖了正在写的 .sql.gz
rsync 默认按修改时间判断更新,但 gzip 压缩过程是先写临时文件再 rename,如果 rsync 正好扫到中间状态,就会同步一个损坏的半成品。这不是 rsync 的 bug,是使用时机错了。
- 压缩完再同步:用
gzip -c backup.sql > backup.sql.gz && rsync -av backup.sql.gz user@backup:/backups/ - 或加原子性保护:压缩到
backup.sql.gz.tmp,成功后再mv backup.sql.gz.tmp backup.sql.gz,rsync 加--exclude='*.tmp' - 别用
--delete,删错一个正在传输的旧备份可能让恢复链断裂 - 远程目录用
chattr +a(ext4)锁定仅追加,防止误删或覆盖已有备份文件
备份不是“跑通命令就行”,最常失效的环节藏在退出码、文件完整性、并发写入竞争这些细节里。一次没校验的 $?,可能让半年后的恢复变成一场数据考古。