编辑 | blame | 历史 | 原始文档

数据库备份与还原操作步骤(traffic_audit)

整理于 2026-09-21。**备份 = 用 mysqldump 导出全库 sql**;**还原 = 把这个 sql 喂回 mysql**。
面向自己动手操作,命令都可以直接复制。

0. 环境速查

项 值
服务端 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

两个坑先记住

  1. 连接参数写 --host=127.0.0.1;写成 -h127.0.0.1 会被解析成主机名 127,直接连不上。
  2. 输出文件用 --result-file= 让 mysqldump 自己写,不要用 > 重定向(中文路径 + PowerShell 引号容易翻车)。

1. 备份(导出全库)

$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(此时不带建库语句,只导结构和数据)。


2. 验证「是不是真导全了」(三步,强度递增)

导出完**不要直接发人**,按下面三步核。

第 1 步:结构齐不齐

# 备份里的 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') 事件;"

第 2、3 步:还原到临时库,比行数 + 比内容

原理:把备份里的库名换成 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;'

3. 还原(把备份装到这台或另一台机器)

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,是破坏性的。

4. 常见问题

现象 原因 / 处理
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=...

5. 本次实测记录(2026-09-21)

  • 备份文件:_给同事_2026-09-21\traffic_audit_full_20260921.sql,52,030,977 字节(约 49.6 MB),导出时间 10:34:57。
  • SHA256:832B518F45313420...(完整值见 _给同事_2026-09-21\还原说明_2026-09-21.md)。
  • 验证结果:29/29 张表结构齐、行数一致(合计 128,962 行)、CHECKSUM TABLE 一致、逐行 SHA256 一致。
  • 经验教训:10:17 先导了一份,10:34 复查发现源库已被改动(investment_system 148→277、audit_result 3393→3421、import_batch 417→419),旧备份已过期。
    → 备份是某一时刻的快照;只要之后还在往系统里导数据、跑审核,备份就旧了。交付/归档前**最后再导一次**。

判断备份新旧的最快办法:看文件名里的时间戳,与 import_batch 的 MAX(created_at) 比一下。