该 LOAD DATA
语句将数据文件加载到表中。该语句可以加载服务器主机上的文件,也可以加载客户端主机上的文件,如果指定了 LOCAL
关键字。
该 LOCAL
版本的 LOAD DATA
存在两个潜在的安全问题:
-
因为
LOAD DATA LOCAL
是一个 SQL 语句,解析发生在服务器端,并且从客户端主机到服务器主机的文件传输是由 MySQL 服务器发起的,该服务器告诉客户端程序传输语句中指定的文件。在理论上,一个修补的服务器可以告诉客户端程序传输服务器选择的文件,而不是语句中指定的文件。这样,服务器可以访问客户端主机上客户端用户有读取权限的任何文件。(一个修补的服务器实际上可以对任何语句(不仅仅是LOAD DATA LOCAL
)发出文件传输请求,因此更基本的问题是客户端不应该连接到不受信任的服务器。) -
在 Web 环境中,客户端来自 Web 服务器,在这种环境中,用户可以使用
LOAD DATA LOCAL
读取 Web 服务器进程有读取权限的任何文件(假设用户可以对 SQL 服务器运行任何语句)。在这种环境中,客户端相对于 MySQL 服务器实际上是 Web 服务器,而不是远程程序被用户连接到 Web 服务器。
为了避免连接到不受信任的服务器,客户端可以建立安全连接并使用 --ssl-mode=VERIFY_IDENTITY
选项和适当的 CA 证书来验证服务器身份。要实现这种级别的验证,必须首先确保服务器的 CA 证书可靠地提供给副本,否则将导致可用性问题。有关更多信息,请参阅 Command Options for Encrypted Connections。
为了避免 LOAD DATA
问题,客户端应该避免使用 LOCAL
,除非采取了适当的客户端预防措施。
为了控制本地数据加载,MySQL 允许启用或禁用该功能。MySQL 还允许客户端限制本地数据加载操作到指定目录中的文件。
管理员和应用程序可以按照以下方式配置是否允许本地数据加载:
-
在服务器端:
-
系统变量
local_infile
控制服务器端的LOCAL
功能。根据local_infile
设置,服务器拒绝或允许客户端请求本地数据加载。 -
默认情况下,
local_infile
是禁用的。(这与 MySQL 的前版本不同。)要使服务器明确拒绝或允许LOAD DATA LOCAL
语句(无论客户端程序和库如何在构建时或运行时配置),请使用local_infile
禁用或启用 mysqld。local_infile
也可以在运行时设置。
-
-
在客户端:
-
在
ENABLED_LOCAL_INFILE
CMake选项控制MySQL客户端库的编译默认LOCAL
功能(见第2.8.7节,“MySQL源配置选项”)。因此,客户端如果没有明确的安排,将根据ENABLED_LOCAL_INFILE
设置在MySQL构建时指定的默认值启用或禁用LOCAL
功能。 -
默认情况下,MySQL二进制分布中的客户端库是与
ENABLED_LOCAL_INFILE
禁用编译的。如果您从源代码编译MySQL,可以根据客户端是否应该禁用或启用LOCAL
功能来配置它。 -
对于使用C API的客户端程序,本地数据加载功能是由MySQL客户端库中的默认值确定的。要明确启用或禁用它,请使用
mysql_options()
C API函数禁用或启用MYSQL_OPT_LOCAL_INFILE
选项。见mysql_options()。 -
对于mysql客户端,本地数据加载功能是由MySQL客户端库中的默认值确定的。要明确禁用或启用它,请使用
--local-infile=0
或--local-infile[=1]
选项。 -
对于mysqlimport客户端,默认情况下不使用本地数据加载。要明确禁用或启用它,请使用
--local=0
或--local[=1]
选项。 -
如果您在Perl脚本或其他读取选项文件的[client]组的程序中使用
LOAD DATA LOCAL
,可以在该组中添加一个local-infile
选项设置。为了避免程序不理解该选项的问题,可以使用loose-
前缀:[client] loose-local-infile=0
或:
[client] loose-local-infile=1
-
在所有情况下,客户端成功使用本地加载操作还需要服务器允许本地加载。
-
如果LOCAL
功能在服务器或客户端禁用,客户端尝试发出LOAD DATA LOCAL
语句时将收到以下错误消息:
ERROR 3950 (42000): Loading local data is disabled; this must be
enabled on both the client and server side
MySQL客户端库使客户端应用程序可以限制本地数据加载操作到指定目录中的文件。某些MySQL客户端程序利用了这种功能。
使用C API的客户端程序可以使用mysql_options()
C API函数的MYSQL_OPT_LOCAL_INFILE
和MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项来控制哪些文件允许加载数据(见mysql_options())。
MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项的效果取决于LOCAL
数据加载是否启用或禁用:
-
如果
LOCAL
数据加载启用,或者在MySQL客户端库中默认启用,或者通过明确启用MYSQL_OPT_LOCAL_INFILE
启用,MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项无效。 -
如果禁用了
LOCAL
数据加载,或者在MySQL客户端库中默认禁用,或者通过明确禁用MYSQL_OPT_LOCAL_INFILE
,那么可以使用MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项来指定允许的目录,以便加载本地文件。在这种情况下,LOCAL
数据加载是允许的,但仅限于位于指定目录中的文件。解释MYSQL_OPT_LOAD_DATA_LOCAL_DIR
值的方式如下:-
如果值为空指针(默认),那么它不命名任何目录,结果是没有文件被允许用于
LOCAL
数据加载。 -
如果值是一个目录路径名,
LOCAL
数据加载是允许的,但仅限于位于命名目录中的文件。比较目录路径名和要加载的文件路径名是大小写敏感的,不管基础文件系统的大小写敏感性如何。
-
MySQL客户端程序使用以下mysql_options()
选项:
-
客户端mysql有一个
--load-data-local-dir
选项,该选项接受目录路径或空字符串。mysql使用选项值来设置MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项(空字符串将值设置为空指针)。--load-data-local-dir
选项的效果取决于LOCAL
数据加载是否启用:-
如果
LOCAL
数据加载启用,或者在MySQL客户端库中默认启用,或者通过指定--local-infile[=1]
,那么--load-data-local-dir
选项将被忽略。 -
如果
LOCAL
数据加载禁用,或者在MySQL客户端库中默认禁用,或者通过指定--local-infile=0
,那么--load-data-local-dir
选项将生效。
当
--load-data-local-dir
选项生效时,选项值指定了本地数据文件必须位于的目录。比较目录路径名和要加载的文件路径名是大小写敏感的,不管基础文件系统的大小写敏感性如何。如果选项值为空字符串,那么它不命名任何目录,结果是没有文件被允许用于本地数据加载。 -
-
mysqlimport为每个文件设置
MYSQL_OPT_LOAD_DATA_LOCAL_DIR
,以便目录包含文件是允许的本地加载目录。 -
对于对应于
LOAD DATA
语句的数据加载操作,mysqlbinlog从二进制日志事件中提取文件,写入临时文件到本地文件系统,并写入LOAD DATA LOCAL
语句,以便加载文件。默认情况下,mysqlbinlog将这些临时文件写入操作系统特定的目录。--local-load
选项可以用于明确指定mysqlbinlog应该准备本地临时文件的目录。因为其他进程可以将文件写入默认的系统特定目录,因此建议指定
--local-load
选项以mysqlbinlog指定不同的目录用于数据文件,然后在处理mysqlbinlog的输出时指定同一个目录,方法是指定--load-data-local-dir
选项到mysql。
MySQL Shell 提供了一些实用程序来转储表、模式或服务器实例,并将其加载到其他实例中。当您使用这些实用程序处理数据时,MySQL Shell 提供了附加功能,例如输入预处理、多线程并行加载、文件压缩和解压缩,以及访问 Oracle Cloud Infrastructure Object Storage 存储桶的功能。为了获得最佳功能,请始终使用 MySQL Shell 的最新版本的转储和加载实用程序。
MySQL Shell 的数据上传实用程序使用 LOAD DATA LOCAL INFILE
语句来上传数据,因此目标服务器实例上的 local_infile
系统变量必须设置为 ON
。您可以在上传数据之前设置它,然后在上传完成后将其删除。实用程序安全地处理文件传输请求,以解决本主题中讨论的安全考虑事项。
MySQL Shell 包括以下转储和加载实用程序:
-
Table export utility
util.exportTable()
-
将 MySQL 关系表导出到数据文件中,该文件可以使用 MySQL Shell 的并行表导入实用程序上传到 MySQL 服务器实例中,或者导入到其他应用程序中,或者用作逻辑备份。该实用程序具有预设选项和自定义选项,以生成不同的输出格式。
-
Parallel table import utility
util.importTable()
-
将数据文件导入到 MySQL 关系表中。数据文件可以是 MySQL Shell 的表导出实用程序的输出,或者其他格式,支持该实用程序的预设和自定义选项。该实用程序可以在添加数据到表之前执行输入预处理,可以合并多个数据文件到单个关系表中,并自动解压缩压缩文件。
-
Instance dump utility
util.dumpInstance()
, schema dump utilityutil.dumpSchemas()
, and table dump utilityutil.dumpTables()
-
将实例、模式或表导出到一组转储文件中,然后可以使用 MySQL Shell 的转储加载实用程序将其上传到 MySQL 实例中。该实用程序提供 Oracle Cloud Infrastructure Object Storage 流式传输、MySQL HeatWave Service 兼容性检查和修改、以及执行 dry run 以标识问题的能力。
-
Dump loading utility
util.loadDump()
-
将使用 MySQL Shell 的实例、模式或表转储实用程序创建的转储文件导入到 MySQL HeatWave Service DB System 或 MySQL 服务器实例中。该实用程序管理上传过程,提供远程存储的数据流式传输、表或表块的并行加载、进度状态跟踪、恢复和重置能力,以及并发加载的选项,同时转储仍在进行中。MySQL Shell 的并行表导入实用程序可以与转储加载实用程序结合使用,以在上传数据到目标 MySQL 实例之前修改数据。
有关实用程序的详细信息,请参阅 MySQL Shell 实用程序。