Centos7、Mysql8.0 load_file函数返回为空的终极解决方法--暨selinux的深入理解

零、问题背景

        最近想换房,为了方便自己对比感兴趣的房子,因此决定将目标房源的基本信息放在表里,特别是要一目了然的看到众多房子的各种图纸和照片,因此决定要在Mysql8.0.34数据库中以二进制形式保存图片(抛开合理性和性能暂且不谈,这里只说技术实现),许多帖子说使用load_file函数来实现,但我按照其他人的方法实操时一直返回NULL,还好历经千辛万苦终于解决了,现将过程与思路加以总结,存档留念。

一、准备工作

1.1、服务器与数据库版本

        我是用 rpm 方式安装的 MySQL 8.0.23 版本,服务器操作系统是Centos 7.9 虚拟机资源  2C 4G 40G

1.2、表结构

        下图是我的表结构,其中有几个字段是 mediumblob类型,用来存放大小约为200k以内的图片。

1.3、图片保存位置

        为了便于后续业务扩展,也出于数据隔离的需要,我用服务器上自定义了 /data/pic/house 路径作为当前业务存储图片的根目录。并在其下面创建了 housepic 和 roomtype两个路径。

二、问题分步展示

2.1、问题展示

        我将一张名为 h_1.jpg 的图片放到  /data/pic/house/roomtype 下,然后使用如下语句尝试查看图片时没能返回预期图片内容,而是返回了NULL。

select load_file('/data/pic/house/roomtype/h_1.jpg');

2.2、原因及secure_file_priv介绍

         load_file 函数返回为 null 的原因,根源在于 MySQL 配置文件中的 “secure_file_priv” 属性取值与load_file 函数使用的路径不一。在具体解决问题之前,应该先了解这一属性的作用和取值范围是什么。

2.2.1、secure_file_priv介绍

        该属性有三类取值,分别为 "NULL"、空值、具体路径字符串。不同取值的含义如下表所示

取值 含义
NULL 不允许读写任何路径下的文件
'' 或 没有值 允许读写任意路径下的文件
字符串(如 /tmp) 允许读写当前路径(如 /tmp)下的文件
2.2.2、secure_file_priv 查看

        在MySQL任意一种客户端中输入如下命令查看。secure_file_priv的默认取值如下图所示,为 “/var/lib/mysql-files/”。说明当前load_file 函数只能操作 “/var/lib/mysql-files/” 路径下的文件。

show variables like '%secure%';

      

2.2.3、secure_file_priv 修改

        通过上面的分析已经知道了问题的原因,下面就是在MySQL的配置文件中修改这一参数的取值。因为我的MySQL是rpm安装版,所以配置文件的名称与路径为: /etc/my.cnf (其他版本操作系统下的MySQL的配置文件位置与名称请自行确认)。同时我希望 MySQL 不限制文件路径,因此 secure_file_priv 取值及展示如下所示:

#关闭mysql的文件读写路径限制,取值为空
secure-file-priv= ''

        需要注意的一点就是,配置文件中应写成 “secure-file-priv” 而非“secure_file_priv”的形式,切切

2.3、效果与终极解决方法

        如果逐位按照上面的方法作了修改,大概率是依然不成功。原因在于没有关闭selinux 。我之前就在selinux 这个坑中挣扎了好久才爬出来。下面就简单聊聊 selinux 是啥,以及为什么会对这个参数有这么大的影响。

2.3.1、selinux是什么、能做什么

        它是“安全增强型 Linux(Security-Enhanced Linux)”的简称,它是 Linux 的一个安全子系统。

        它能对linux系统中,包括root在内的所有用户的行为做管制。它能通过一系列的配置实现 “允许 X 目标,对 Z 对象/资源,做 Y行为 ” (May <subject> do <action> to <object/source>)的访问控制。其中,X多指进程;Y多指X访问的资源,如端口、文件等;Z多指访问或操作规则。

        它有三种工作模式,如下表所示:

模式名称 作用
enforcing 强制模式。阻止并在日志记录违反SELinux规则的行为
permissive 宽容模式。仅在日志记录违反SELinux规则的行为
disabled 关闭模式。关闭SELinux

        selinux 是一套相当复杂的子系统,里面有庞大的配置项需要了解,在此不做进一步的解释,只需要知道它会对 MySQL 的关键行为做校验与限制即可。除非是专门负责安全和服务器运维的工程师需要深入了解selinux各种规则之外,一般的开发人员在遇到linux 的一些校验失败的情况时,可以想到有这样一个东西存在,并且知道通过关闭selinux可以解决大部分的安全校验问题即可

2.3.2、selinux 的关闭与开启

        selinux 的关闭分为临时关闭和永久关闭,下图为临时关闭方式(即设为宽容模式)

        

        下面为永久关闭方法

# 修改 /etc/selinux/config 文件中的  SELINUX=disabled
[root@MySQL01 ~]# vim /etc/selinux/config

# 修改 /etc/sysconfig/selinux 文件中的  SELINUX=disabled
[root@MySQL01 ~]# vim /etc/sysconfig/selinux

2.4、最终效果

        在MySQL 的 secure_file_priv参数设置为理想的值,并且关闭了 selinux 之后,发现可以正常读取到图片了,如下图所示

2.5、补充说明

        存放图片的路径,建议放到 mysql 属组,且赋予 对应的权限。如下图所示

        

三、说在最后

9.1 如何查看centos 版本

cat /etc/redhat-release

9.2、如何查看MySQL版本

select VERSION(); 

9.3、load_file 函数的作用与效率

        它在 MySQL 中的主要作用是读取本地或远程的文件。文件种类涵盖文本、二进制、图片、视频等。因这样的读取方式不够安全,因此建议在受信的环境中使用。

9.4、MySQL 几种操作图片的思路和对比

        可以通过load_file 函数将图片记录到字段中,也可以将图片所在的路径记录到字段中。前者存在安全隐患,后者无法在MySQL中直接看到图片内容。因此对图片的处理方式应根据业务需求等因素综合考虑后选择。

最近更新

  1. TCP协议是安全的吗?

    2023-12-09 15:12:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-09 15:12:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-09 15:12:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-09 15:12:03       20 阅读

热门阅读

  1. [力扣100] 10.滑动窗口的最大值

    2023-12-09 15:12:03       33 阅读
  2. sqlite事务 及 PRAGMA synchronous = OFF;

    2023-12-09 15:12:03       30 阅读
  3. 从零开始搭建链上dex自动化价差套利程序(12)

    2023-12-09 15:12:03       32 阅读
  4. 使用Ansible Expect模块实现自动化交互式任务

    2023-12-09 15:12:03       31 阅读
  5. 第55天:django学习(四)

    2023-12-09 15:12:03       37 阅读