整理于 2026-09-21。**备份 = 用 mysqldump 导出全库 sql**;**还原 = 把这个 sql 喂回 mysql**。
面向自己动手操作,命令都可以直接复制。
| 项 | 值 |
|---|---|
| 服务端 | MySQL 8.0.29,127.0.0.1:3308 |
| 库 / 账号 | 库 traffic_audit,账号 root / 123456 |
| 导出工具 | C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqldump.exe(**必须用 8.0 这个**,与服务端同版本) |
| 日常查数客户端 | D:\mysql\mysql-5.7.41-winx64\bin\mysql.exe |
两个坑先记住
--host=127.0.0.1;写成 -h127.0.0.1 会被解析成主机名 127,直接连不上。--result-file= 让 mysqldump 自己写,不要用 > 重定向(中文路径 + PowerShell 引号容易翻车)。$ts = Get-Date -Format 'yyyyMMdd_HHmmss'
$dir = 'D:\backup' # 路径不要留空格
New-Item -ItemType Directory -Force $dir | Out-Null
$out = Join-Path $dir "traffic_audit_full_$ts.sql"
& 'C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqldump.exe' `
--host=127.0.0.1 --port=3308 --user=root --password=123456 `
--default-character-set=utf8mb4 `
--single-transaction --routines --triggers --events --hex-blob `
--databases traffic_audit `
--result-file=$out
"exit=$LASTEXITCODE"
Get-Item $out | Select-Object Name, Length, LastWriteTime
成功判据:exit=0,文件有几十 MB,且文件最后一行是 -- Dump completed on ...(没有就是中途断了)。
每个参数的作用:
| 参数 | 作用 |
|---|---|
--host=127.0.0.1 --port=3308 |
本机服务端端口(见上「两个坑」) |
--default-character-set=utf8mb4 |
中文不乱码,**必带** |
--single-transaction |
一致性快照,导出期间不锁表,别人照样能用系统 |
--databases traffic_audit |
连 CREATE DATABASE + USE 一起导 → 同事拿到**单个文件**就能整库还原 |
--routines --triggers --events |
本库目前没有这类对象(均为 0),带上只是防将来有 |
--hex-blob |
二进制列安全导出 |
--result-file=... |
直接写文件,绕开重定向的编码/引号问题 |
只导某几张表:把
--databases traffic_audit换成traffic_audit 表1 表2(此时不带建库语句,只导结构和数据)。
导出完**不要直接发人**,按下面三步核。
# 备份里的 CREATE TABLE 条数
(Select-String -Path $out -Pattern '^CREATE TABLE' -Encoding UTF8).Count
# 库里实际表数
& 'D:\mysql\mysql-5.7.41-winx64\bin\mysql.exe' --host=127.0.0.1 --port=3308 --user=root --password=123456 `
-N -B -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='traffic_audit';"
两个数相等(本库是 29)才算结构齐。顺带确认没有 mysqldump 导不出来的对象:
& 'D:\mysql\mysql-5.7.41-winx64\bin\mysql.exe' --host=127.0.0.1 --port=3308 --user=root --password=123456 -e `
"SELECT (SELECT COUNT(*) FROM information_schema.views WHERE table_schema='traffic_audit') 视图,
(SELECT COUNT(*) FROM information_schema.routines WHERE routine_schema='traffic_audit') 存储过程,
(SELECT COUNT(*) FROM information_schema.triggers WHERE trigger_schema='traffic_audit') 触发器,
(SELECT COUNT(*) FROM information_schema.events WHERE event_schema='traffic_audit') 事件;"
原理:把备份里的库名换成 traffic_audit_vfy 导进临时库,与源库逐表比对,比完删库。
$root = 'D:\文档\ChatGPT\traffic-audit'
$vfySql = "$root\_tmp\_verify.sql"
# 2.1 换库名(用 28591 编码做「按字节替换」,不会动坏中文)
$enc = [System.Text.Encoding]::GetEncoding(28591)
$s = $enc.GetString([System.IO.File]::ReadAllBytes($out))
[System.IO.File]::WriteAllBytes($vfySql, $enc.GetBytes($s.Replace('`traffic_audit`', '`traffic_audit_vfy`')))
# 2.2 导入临时库(cmd 的 < 重定向最省事)
$mysql = 'C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe'
& $mysql --host=127.0.0.1 --port=3308 --user=root --password=123456 -e 'DROP DATABASE IF EXISTS traffic_audit_vfy;'
cmd /c "`"$mysql`" --host=127.0.0.1 --port=3308 --user=root --password=123456 --default-character-set=utf8mb4 < `"$vfySql`""
# 2.3 逐表比行数
$tables = & $mysql --host=127.0.0.1 --port=3308 --user=root --password=123456 -N -B `
-e "SELECT table_name FROM information_schema.tables WHERE table_schema='traffic_audit' ORDER BY table_name;"
& $mysql --host=127.0.0.1 --port=3308 --user=root --password=123456 -B -e (($tables |
ForEach-Object { "SELECT '$_' 表,(SELECT COUNT(*) FROM traffic_audit.$_) 源库,(SELECT COUNT(*) FROM traffic_audit_vfy.$_) 备份" }) -join ' UNION ALL ')
逐表两列数字一致 → 行数齐。
最强的一步:比内容(SHA256)。两张表行数一样、内容被改过,上面的方法看不出来,这个方法能:
$md = 'C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqldump.exe'
$common = '--host=127.0.0.1','--port=3308','--user=root','--password=123456','--default-character-set=utf8mb4',
'--single-transaction','--no-create-info','--skip-comments','--order-by-primary','--hex-blob','--compact'
& $md @common traffic_audit "--result-file=$root\_tmp\_cmp_src.sql"
& $md @common traffic_audit_vfy "--result-file=$root\_tmp\_cmp_vfy.sql"
(Get-FileHash "$root\_tmp\_cmp_src.sql").Hash -eq (Get-FileHash "$root\_tmp\_cmp_vfy.sql").Hash # True 才算全
--order-by-primary:按主键排序导出,保证两份文件行顺序一致,才能直接比哈希;本库 29 张表**都有主键**。True → 逐行内容完全一致。收尾(验证完把临时库删掉,别留在服务器上):
& 'C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe' --host=127.0.0.1 --port=3308 --user=root --password=123456 `
-e 'DROP DATABASE IF EXISTS traffic_audit_vfy;'
cmd /c "`"C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe`" --host=127.0.0.1 --port=3308 --user=root --password=123456 --default-character-set=utf8mb4 < `"D:\backup\traffic_audit_full_20260921_103457.sql`""
CREATE DATABASE,**空环境**直接跑即可。CREATE DATABASE IF NOT EXISTS 不报错,但后面 CREATE TABLE 会因表已存在而失败、半途中断。要么先 DROP DATABASE traffic_audit;,要么先确认是空环境。docs/init.sql 去补已有数据的库:它带 DROP TABLE,是破坏性的。| 现象 | 原因 / 处理 |
|---|---|
mysqldump: [Warning] Using a password on the command line interface can be insecure. |
只是警告,不影响结果;想消掉可用 --defaults-extra-file 放密码 |
导入报 Table 'xxx' already exists |
目标库不是空的(见上) |
导入报 Unknown database |
用 --databases 导出的备份不会出现;如果只导了表(没带建库语句),要自己先 CREATE DATABASE traffic_audit |
| 中文变问号/乱码 | 导出、导入两头都要 --default-character-set=utf8mb4 |
| 备份文件只有几百 KB | 十有八九是 --databases 写错库名或连接失败,看退出码和文件末尾有没有 Dump completed |
| 想只备份一张表 | mysqldump ... traffic_audit 表名 --result-file=... |
_给同事_2026-09-21\traffic_audit_full_20260921.sql,52,030,977 字节(约 49.6 MB),导出时间 10:34:57。832B518F45313420...(完整值见 _给同事_2026-09-21\还原说明_2026-09-21.md)。CHECKSUM TABLE 一致、逐行 SHA256 一致。investment_system 148→277、audit_result 3393→3421、import_batch 417→419),旧备份已过期。判断备份新旧的最快办法:看文件名里的时间戳,与
import_batch的MAX(created_at)比一下。