LOAD DATA
语句将数据文件加载到表中。该语句可以加载位于服务器主机上的文件,或者如果指定了 LOCAL
关键字,则加载位于客户端主机上的文件。
LOAD DATA 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 证书对副本可靠地可用,否则会造成可用性问题。有关更多信息,请参阅 加密连接的命令选项。
为了避免 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 源代码配置选项”)。因此,没有进行明确安排的客户端将根据在 MySQL 构建时指定的ENABLED_LOCAL_INFILE
设置禁用或启用LOCAL
功能。默认情况下,MySQL 二进制发行版中的客户端库是用禁用的
ENABLED_LOCAL_INFILE
编译的。如果您从源代码编译 MySQL,请根据没有进行明确安排的客户端是否应该禁用或启用LOCAL
功能,使用禁用或启用的ENABLED_LOCAL_INFILE
配置它。对于使用 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
加载操作还需要服务器允许本地加载。
如果在服务器端或客户端端禁用了 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
值的解释如下如果该值为 null 指针(默认值),则它不命名任何目录,因此不允许任何文件进行
LOCAL
数据加载。如果该值为目录路径名,则允许
LOCAL
数据加载,但仅限于位于命名目录中的文件。无论底层文件系统的区分大小写情况如何,对目录路径名和要加载的文件的路径名的比较都区分大小写。
MySQL 客户端程序按以下方式使用前面的 mysql_options()
选项
mysql 客户端有一个
--load-data-local-dir
选项,它接受目录路径或空字符串。 mysql 使用选项值来设置MYSQL_OPT_LOAD_DATA_LOCAL_DIR
选项(使用空字符串将该值设置为 null 指针)。--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 应准备本地临时文件的目录。由于其他进程可以将文件写入默认的特定于系统的目录,因此建议为 mysqlbinlog 指定
--local-load
选项以指定数据文件的不同目录,然后通过为 mysql 指定--load-data-local-dir
选项来指定同一个目录,以便在处理来自 mysqlbinlog 的输出时指定。
MySQL Shell 提供了许多实用程序来转储表、模式或服务器实例,并将它们加载到其他实例中。当您使用这些实用程序处理数据时,MySQL Shell 提供了其他功能,例如输入预处理、多线程并行加载、文件压缩和解压缩以及处理对 Oracle Cloud Infrastructure Object Storage 存储桶的访问。为了获得最佳功能,请始终使用 MySQL Shell 的转储和转储加载实用程序的最新版本。
MySQL Shell 的数据上传实用程序使用 LOAD DATA LOCAL INFILE
语句上传数据,因此 local_infile
系统变量必须在目标服务器实例上设置为 ON
。您可以在上传数据之前执行此操作,然后在上传数据后再次删除它。这些实用程序安全地处理文件传输请求,以解决本主题中讨论的安全问题。
MySQL Shell 包含以下转储和转储加载实用程序
- 表导出实用程序
util.exportTable()
将 MySQL 关系表导出到数据文件,该文件可以使用 MySQL Shell 的并行表导入实用程序上传到 MySQL 服务器实例,导入到其他应用程序,或用作逻辑备份。该实用程序具有预设选项和自定义选项,可以生成不同的输出格式。
- 并行表导入实用程序
util.importTable()
将数据文件导入到 MySQL 关系表。该数据文件可以是 MySQL Shell 的表导出实用程序的输出,也可以是该实用程序的预设和自定义选项支持的其他格式。该实用程序可以在将数据添加到表之前进行输入预处理。它可以接受多个数据文件以合并到单个关系表中,并自动解压缩压缩文件。
- 实例转储实用程序
util.dumpInstance()
、模式转储实用程序util.dumpSchemas()
和表转储实用程序util.dumpTables()
将实例、模式或表导出到一组转储文件,然后可以使用 MySQL Shell 的转储加载实用程序将这些文件上传到 MySQL 实例。这些实用程序提供了 Oracle Cloud Infrastructure Object Storage 流式传输、HeatWave Service 兼容性检查和修改,以及在继续进行转储之前执行试运行以识别问题的能力。
- 转储加载实用程序
util.loadDump()
将使用 MySQL Shell 实例、模式或表转储工具创建的转储文件导入 HeatWave 服务数据库系统或 MySQL Server 实例。该工具管理上传过程,并提供来自远程存储的数据流、表或表块的并行加载、进度状态跟踪、恢复和重置功能,以及在转储仍在进行时进行并发加载的选项。MySQL Shell 的并行表导入工具可以与转储加载工具结合使用,在将数据上传到目标 MySQL 实例之前修改数据。
有关这些工具的详细信息,请参见 MySQL Shell 工具。