文档首页
MySQL 8.4 参考手册
相关文档 下载此手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  LOAD DATA LOCAL 的安全注意事项

8.1.6 LOAD DATA LOCAL 的安全注意事项

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 禁用或启用启动 mysqldlocal_infile 也可以在运行时设置。

  • 在客户端

    • ENABLED_LOCAL_INFILE CMake 选项控制 MySQL 客户端库的编译时默认 LOCAL 功能(参见 第 2.8.7 节,“MySQL 源代码配置选项”)。因此,没有进行明确安排的客户端会根据在 MySQL 构建时指定的 ENABLED_LOCAL_INFILE 设置禁用或启用 LOCAL 功能。

    • 默认情况下,MySQL 二进制发行版中的客户端库使用 ENABLED_LOCAL_INFILE 禁用编译。如果从源代码编译 MySQL,请使用 ENABLED_LOCAL_INFILE 禁用或启用配置,这取决于没有进行明确安排的客户端是否应禁用或启用 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 加载操作也需要服务器允许本地加载。

如果在服务器或客户端上禁用了 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_INFILEMYSQL_OPT_LOAD_DATA_LOCAL_DIR 选项来控制允许加载数据的哪些文件(参见 mysql_options())。

MYSQL_OPT_LOAD_DATA_LOCAL_DIR 的效果取决于 LOCAL 数据加载是启用还是禁用

  • 如果通过 MySQL 客户端库中的默认值或通过显式启用 MYSQL_OPT_LOCAL_INFILE 来启用 LOCAL 数据加载,则 MYSQL_OPT_LOAD_DATA_LOCAL_DIR 选项无效。

  • 如果通过 MySQL 客户端库中的默认值或通过显式禁用 MYSQL_OPT_LOCAL_INFILE 来禁用 LOCAL 数据加载,则 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 数据加载是启用还是禁用

    --load-data-local-dir 适用时,选项值指定本地数据文件必须位于其中的目录。目录路径名和要加载的文件的路径名的比较区分大小写,而与底层文件系统的区分大小写无关。如果选项值为空字符串,则它不命名任何目录,导致不允许任何文件进行本地数据加载。

  • mysqlimport 为其处理的每个文件设置 MYSQL_OPT_LOAD_DATA_LOCAL_DIR,以便包含该文件的目录成为允许的本地加载目录。

  • 对于对应于 LOAD DATA 语句的数据加载操作,mysqlbinlog 从二进制日志事件中提取文件,将它们作为临时文件写入本地文件系统,并写入 LOAD DATA LOCAL 语句以导致加载文件。默认情况下,mysqlbinlog 将这些临时文件写入特定于操作系统的目录。--local-load 选项可用于明确指定 mysqlbinlog 应准备本地临时文件的目录。

    由于其他进程可以将文件写入默认的特定于系统目录,因此建议将 --local-load 选项指定给 mysqlbinlog 以指定数据文件的不同目录,然后通过将 --load-data-local-dir 选项指定给 mysql 来指定同一目录,以便在处理来自 mysqlbinlog 的输出时使用。

MySQL Shell 和本地数据加载

MySQL Shell 提供了许多实用程序来转储表、模式或服务器实例,并将它们加载到其他实例中。当您使用这些实用程序来处理数据时,MySQL Shell 会提供额外的功能,例如输入预处理、多线程并行加载、文件压缩和解压缩,以及处理对 Oracle Cloud Infrastructure 对象存储桶的访问。为了获得最佳功能,始终使用 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 对象存储流、HeatWave 服务兼容性检查和修改,以及在继续进行转储之前识别问题的试运行功能。

转储加载实用程序 util.loadDump()

将使用 MySQL Shell 实例、模式或表转储实用程序创建的转储文件导入 HeatWave 服务数据库系统或 MySQL 服务器实例。该实用程序管理上传过程,并提供来自远程存储的数据流、表或表块的并行加载、进度状态跟踪、恢复和重置功能,以及转储仍在进行时进行并发加载的选项。MySQL Shell 的并行表导入实用程序可以与转储加载实用程序结合使用,以便在将数据上传到目标 MySQL 实例之前修改数据。

有关实用程序的详细信息,请参阅 MySQL Shell 实用程序