ThinkPHP 6.9 不提供直接导出/还原 SQL 文件的功能,必须依赖 mysqldump 和 mysql 原生命令;正确做法是通过 --defaults-file 安全调用 mysqldump 导出含结构与数据的 SQL 文件,并存于 Web 不可访问路径,还原时需先清空目标库再导入。

ThinkPHP 6.9 本身不提供直接执行 SQL 文件并导出数据表的功能。它没有内置的“从 .sql 文件还原表结构+数据”或“把当前表导出为 .sql 文件”的命令或方法。这类操作属于数据库维护范畴,必须依赖 MySQL 原生命令(如 mysqldump 和 mysql),而非框架层的 Db 类或模型。
真正可靠、安全、生产可用的导出方式只有一种:调用系统级 mysqldump 命令生成 SQL 文件,而不是用 PHP 拼 SQL、遍历数据、手写 CREATE TABLE。
✅ 正确导出数据表(含结构 + 数据)的方法
你需要在服务器上执行 shell 命令,不是在 TP6 代码里写 Db::query("CREATE...")。
1. 确保环境支持 mysqldump
- Web 进程(如
www-data)需有权限执行mysqldump - 检查
php.ini中未禁用exec/shell_exec - 推荐用配置文件传密,避免密码暴露:
# 创建 /www/wwwroot/myapp/my.cnf(权限设为 600) [client] user = your_db_user password = your_secure_password host = 127.0.0.1
2. 执行导出命令(建议加时间戳)
mysqldump \ --defaults-file=/www/wwwroot/myapp/my.cnf \ --single-transaction \ --routines \ --triggers \ --events \ --no-definer \ your_database_name \ > /www/backup/backup_shop_$(date +%Y%m%d_%H%M%S).sql
-
--single-transaction:保证大表一致性,不锁表 -
--no-definer:避免迁移时因用户不存在导致失败 - 输出路径必须不可通过 Web 访问(如
/www/backup/,绝不能是/public/)
3. PHP 中安全触发(可选,仅限可信后台)
如果需要在 ThinkPHP 后台点击按钮触发备份,可用以下逻辑(注意权限与错误处理):
立即学习“PHP免费学习笔记(深入)”;
$cmd = 'mysqldump --defaults-file=/www/wwwroot/myapp/my.cnf --single-transaction --no-definer your_db_name > /www/backup/backup_'.date('Ymd_His').'.sql 2>&1';
exec($cmd, $output, $return_var);
if ($return_var !== 0) {
throw new \Exception('备份失败:' . implode("\n", $output));
}- 务必检查
$return_var,非 0 即失败 - 不要拼接用户输入到
$cmd中,杜绝 shell 注入
❌ 错误做法(常见坑)
用
Db::table('user')->select()遍历再拼 INSERT:
→ 丢索引、丢外键、丢字段类型、丢注释、不支持 BLOB、大表内存溢出把
.sql文件放public/目录下供下载:
→ 等于公开数据库,严重安全风险在代码里用
file_get_contents()读取 SQL 再Db::execute()执行:
→ 不支持多语句(MySQL 默认禁用),无法建库/删表/设字符集,极易中断用
CREATE TABLE IF NOT EXISTS直接覆盖导入:
→ 旧表残留脏数据、错误索引、多余字段,后续业务出错难排查
? 补充:导出后如何还原?
还原不是“执行 SQL 文件”,而是:
- 先清空目标库(
DROP DATABASE xxx; CREATE DATABASE xxx;)或至少TRUNCATE TABLE - 关闭外键检查:
SET FOREIGN_KEY_CHECKS = 0; - 用
mysql --defaults-file=... your_db < file.sql导入 - 切勿用
Db::execute(file_get_contents(...))—— 它根本跑不通
不复杂但容易忽略。



















