备份目录权限隔离必须依赖linux文件系统权限和os用户身份,mysql自身不管理备份文件权限;应为每个租户创建独立系统用户、专属备份目录(700权限)、以对应用户执行脚本;mysqldump须按租户分库导出并命名含租户标识与时间戳;恢复时须限定数据库名及用户权限。

备份目录权限隔离必须靠操作系统级控制
MySQL 自身不管理备份文件的读写权限,多租户场景下如果所有备份都写进同一个 /backup 目录,靠数据库账号区分毫无意义。真正起作用的是 Linux 文件系统权限和运行备份命令的 OS 用户身份。
实操建议:
- 为每个租户创建独立系统用户(如
tenant_a、tenant_b),不要共用mysql或root - 每个租户的备份目录归属其对应用户,权限设为
700(如chown tenant_a:tenant_a /backup/tenant_a) - 备份脚本必须以租户对应用户身份执行(用
sudo -u tenant_a bash backup.sh,而非在 root 下 chmod 一堆子目录) - 避免使用
mysqldump --result-file直接写入共享路径——该参数由 MySQL 进程自身写文件,权限继承 mysqld 用户,无法隔离
mysqldump 要按租户分库导出,不能全库一把梭
一个 MySQL 实例里混存多个租户数据库(如 db_tenant_a、db_tenant_b)很常见,但 mysqldump --all-databases 会把所有库打成一个文件,后续恢复或审计时根本分不清归属。
实操建议:
- 动态获取租户对应数据库名:用
mysql -Nse "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME LIKE 'db_%'"配合租户前缀过滤 - 每个租户只 dump 自己的库:
mysqldump -u backup_user -p'xxx' db_tenant_a > /backup/tenant_a/db_tenant_a_$(date +%F).sql - 禁止给备份用户
SELECT权限到mysql、information_schema等系统库——防止跨租户探测 - 若用 Percona XtraBackup,同样要限制
--databases参数值,不能留空或写*
备份文件名必须带租户标识和时间戳
没有明确命名规则的备份文件,在故障恢复时极易选错。比如 backup.sql 这种名字,三天后连自己都记不清是哪个租户哪天的。
实操建议:
- 固定格式:
tenant_id_dbname_date_time_checksum.sql,例如tenant_a_db_tenant_a_2024-06-15_143022_8a3f.sql - 时间戳用
$(date +\%Y-\%m-\%d_\%H\%M\%S),避免空格和冒号(Windows/FTP 不友好) - 加简单校验码(如
md5sum $file | cut -c-4),防止同名覆盖后无法识别是否被篡改 - 不要依赖备份脚本所在目录名或环境变量临时拼接——这些容易在 cron 或容器中失效
恢复操作必须限定数据库名和用户权限
备份做得再隔离,恢复时一句 mysql 就可能把 A 租户的 SQL 执行进 B 租户的连接上下文里。更危险的是,SQL 文件里若含 <code>CREATE DATABASE 或 USE xxx,可能直接建库或切库到非预期位置。
实操建议:
- 恢复前先检查 SQL 文件头:用
head -n 20 backup.sql | grep -E '^(CREATE DATABASE|USE )',发现就手动删或用 sed 清洗 - 强制指定目标库:
mysql -u tenant_a_ro -p'xxx' db_tenant_a ,绝不省略最后的数据库名参数 - 租户恢复账号仅授予对应库的
INSERT, CREATE, DROP, ALTER,禁止GRANT OPTION和跨库权限 - 测试环境恢复务必用
--one-database参数(mysql --one-database db_tenant_a ),忽略文件内其他 USE 语句
租户隔离真正的难点不在备份生成那一刻,而在于整个生命周期里权限、路径、命名、恢复上下文四个点始终对齐。漏掉任意一环,所谓“隔离”就只剩心理安慰。











