可靠的数据库备份必须使用 mysqldump 原生命令,禁用 php 拼接执行;导出需加 --single-transaction 等参数保证一致性;还原前须 drop database 或 truncate table 并禁用外键检查;备份文件严禁放 public 目录,应存于 web 不可访问路径并校验权限。

备份时直接导出 SQL 文件,别依赖框架模型
ThinkPHP 的 Db 类或模型本身不提供结构+数据一体导出能力,强行用 select() 遍历再拼 SQL 容易丢字段类型、索引、外键和注释。真正可靠的备份必须走原生 MySQL 客户端。
- 用系统命令
mysqldump,不是 PHP 的exec()拼接字符串——后者容易被 shell 注入,且权限、路径、编码问题一堆 - 确保 Web 进程能执行
mysqldump:检查php.ini中disable_functions是否禁了exec或shell_exec - 导出时加
--single-transaction --routines --triggers --events,否则大表可能锁死,存储过程和事件会丢失 - 文件名建议带时间戳和数据库名,比如
backup_shop_202405201430.sql,避免覆盖
还原前必须清空目标库,不能只用 INSERT IGNORE
还原不是“追加数据”,而是重建状态。直接执行备份 SQL 文件时,如果目标库已有同名表,CREATE TABLE IF NOT EXISTS 会跳过建表,但旧表里的脏数据、残留字段、错误索引全留着,后续查询或迁移就出问题。
- 还原脚本第一件事是执行
DROP DATABASE+CREATE DATABASE,而不是USE xxx后硬怼 SQL - 如果不能删库(如共享库),至少用
TRUNCATE TABLE清空每张表,并确认外键约束已临时关闭:SET FOREIGN_KEY_CHECKS = 0; -
mysql命令行导入时加-f参数没用——它只是跳过错误继续执行,不是帮你兜底,反而掩盖表结构不匹配的问题
ThinkPHP 环境下执行 mysqldump 和 mysql 的权限坑
Web 进程(如 www-data、nginx)通常没有访问 MySQL socket 或远程登录权限,mysqldump: Got error: 1045: Access denied 是最常见报错。
- 不要把数据库密码写在命令行里(
mysqldump -u root -p123456),会被ps aux看到,也违反安全规范 - 改用配置文件方式:新建
/etc/mysql/debian.cnf(或项目目录下my.cnf),写入[client]段,设user和password,然后用mysqldump --defaults-file=/path/to/my.cnf db_name - 确认 MySQL 用户有
SELECT(备份)、LOCK TABLES(一致性)、SHOW VIEW(视图)权限;还原还需CREATE、DROP、ALTER - PHP 执行命令后,务必检查
$return_var:非 0 就代表失败,不能只看输出内容是否为空
备份文件不能直接放 public/ 目录下供下载
有人图省事把 backup_20240520.sql 放在 public/ 下,加个链接让用户点开下载——这等于把数据库裸奔扔上网。
- SQL 文件含完整表结构和明文数据,泄露即沦陷。必须存在
runtime/backup/或../private_backup/这类 Web 无法直访的路径 - 提供下载接口时,用 ThinkPHP 的
response()->download(),并校验管理员 Session,不暴露真实路径 - 备份文件建议用
gz压缩,既减体积又天然防文本直接浏览;解压权限也要控制,别让gunzip可被任意调用
备份脚本最难的从来不是语法,而是权限链路上每一步的隐式依赖:MySQL 用户权限、PHP 进程能力、文件系统位置、网络隔离策略。少一个环节,看起来跑通了,其实早埋了雷。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











