SELECT INTO OUTFILE 不受事务隔离级别影响,其失败主因是三类底层拦截:FILE权限缺失、secure_file_priv路径限制、AppArmor/SELinux策略阻止。

SELECT INTO OUTFILE 本身不加表锁,也不受事务隔离级别影响——它根本不在事务内执行。
你遇到的“加锁限制”大概率是误判。真正卡住你的,从来不是 MVCC 或 REPEATABLE READ 这类设置,而是三类底层拦截:
- MySQL 用户缺少
FILE全局权限 -
secure_file_priv配置强制限定可写路径 - 操作系统级安全模块(AppArmor / SELinux)拒绝写入
下面分点说清怎么做、为什么、容易踩什么坑。
确认 FILE 权限是否真已授予
FILE 是全局权限,不能按库或表授予。常见错误是执行了 GRANT FILE ON mydb.* TO 'u'@'h',结果报错 ERROR 1221 (HY000)。
- 正确写法只有这一种:
GRANT FILE ON *.* TO 'lea'@'localhost' - 授完必须
FLUSH PRIVILEGES,否则不生效 - 验证方式:
SHOW GRANTS FOR 'lea'@'localhost',确认输出里有GRANT FILE ON *.*
检查 secure_file_priv 是否锁死了路径
这是最常被忽略的硬性开关。MySQL 启动时若设置了 secure_file_priv,SELECT INTO OUTFILE 只能往该目录(或其子目录)写,其他路径一律 Errcode: 13,且不提示真实原因。
- 查当前值:
SELECT @@global.secure_file_priv - 若返回非空路径(如
/var/lib/mysql-files/),你就只能往那里写,或改配置 - 修改方法:在
/etc/mysql/my.cnf的[mysqld]段下加一行:secure_file_priv = ""(清空表示不限制),然后重启 MySQL - 注意:设为空字符串在某些新版 MySQL 中已被弃用,更稳妥的是显式指定一个你可控的目录,比如
secure_file_priv = /home/datam/xfers/
绕过 AppArmor 或 SELinux 的静默拦截
即使 MySQL 用户有权限、目录 chmod 777、owner 设为 mysql,Errcode: 13 仍可能来自内核级策略。Ubuntu 默认启用 AppArmor,CentOS/RHEL 默认启用 SELinux,它们会按 profile 限制进程能访问的路径。
- Ubuntu 上检查:
sudo aa-status | grep mysqld,如果看到/usr/sbin/mysqld在 enforce 模式,就确认是它挡路 - 临时放行(测试用):
sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/usr.sbin.mysqld && sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld - 永久放行:编辑
/etc/apparmor.d/usr.sbin.mysqld,在/var/log/mysql/ r,下新增一行:/home/datam/xfers/** rwk,,再执行sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld - SELinux 用户请用
setsebool -P mysqld_disable_trans=1,或更细粒度地chcon -t mysqld_db_t /home/datam/xfers/
真正麻烦的点在于:这三类限制是叠加生效的,缺一不可。少配一项,SELECT INTO OUTFILE 就会静默失败,而错误信息永远只显示 “Can't create/write to file”,看不出到底是权限、配置还是策略在拦。


















