推荐使用 mysqldump 命令行工具导出 SQL 文件,而非 PHP 手动拼接;需配置安全参数、正确设置 HTTP 头、避免内存溢出,并优先保障兼容性与完整性。

PHP 本身不提供直接导出完整 SQL 文件的内置函数,必须自己拼接结构、遍历表、生成 CREATE TABLE 和 INSERT 语句;用 mysqldump 命令行工具才是生产环境推荐做法。
用 exec() 调用 mysqldump 最稳
这是最可靠、兼容性最好、性能开销最低的方式。前提是服务器允许执行系统命令且已安装 MySQL 客户端工具。
-
mysqldump自动处理字符集、转义、外键约束、存储过程等边缘情况,PHP 手写几乎不可能全覆盖 - 需确保 PHP 进程有权限读取数据库 + 写入目标路径,且
mysqldump在$PATH中(或写绝对路径,如/usr/bin/mysqldump) - 敏感信息(密码)不要明文传参,改用配置文件方式:
--defaults-extra-file=/tmp/my.cnf,该文件权限必须是600 - 示例命令(安全写法):
mysqldump --defaults-extra-file=/tmp/dump.cnf --single-transaction --routines --triggers database_name > /var/export/backup_2024.sql
mysqli 手动拼 SQL 的典型陷阱
仅适合极简场景(比如只导一张小表、无索引/触发器/视图),但很多人误以为“能跑就行”,结果导出的 SQL 在恢复时失败。
- 忘记设置连接字符集,导致
SHOW CREATE TABLE返回乱码或截断,应先执行SET NAMES utf8mb4 -
SELECT * FROM table导出数据时,没用mysqli_fetch_assoc()+array_map('addslashes', ...),直接拼字符串会崩在单引号、反斜杠、换行符上 - 没处理
NULL值:要写成NULL字面量,不能加引号;也没区分数字型字段(不加引号)和字符串字段(加引号) - 没跳过
information_schema或performance_schema系统库,一并导出会报错
导出大表时内存和超时怎么破
用 PHP 逐行读取再拼 SQL,很容易触发 memory_limit 或 max_execution_time,尤其当单表超 10 万行。
- 禁用输出缓冲:
ob_end_clean(),避免内容先存内存再输出 - 用
mysqli_use_result()替代mysqli_store_result(),让结果集不全加载进 PHP 内存 - 每 1000 行
flush()一次,并调用ob_flush(),防止 Web 服务器缓存阻塞 - 关键:不要把整个 SQL 字符串存在变量里,而是一边查一边
echo或fwrite()到临时文件
导出文件名和 HTTP 头容易漏设
很多代码能生成 SQL 内容,但用户点下载后得到一个无扩展名、乱码、被浏览器当成 HTML 打开的文件。
- 必须设三组头:
Content-Type: text/plain; charset=utf-8、Content-Disposition: attachment; filename="dump.sql"、Content-Transfer-Encoding: binary - 文件名含中文?用
rawurlencode()编码,再包裹双引号,例如:filename="dump_".rawurlencode('用户表').".sql" - 导出前检查是否已有输出(
headers_sent()),否则 header 失效,SQL 内容会混在 HTML 里 - 导出完成后加
exit;,避免后续脚本输出干扰文件流
真正难的不是“怎么拼出 SQL”,而是覆盖所有边界:空表、含 BLOB 字段、自增 ID、分区表、MySQL 8.0+ 的角色权限语句……这些 mysqldump 默认支持,手写逻辑几乎必然遗漏。别为了“纯 PHP”放弃成熟方案。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











