MySQL8 中文参考(二十三)
7.6.9.2 密钥环服务
MySQL Server 支持一个密钥环服务,使内部组件和插件能够安全地存储敏感信息以供以后检索。MySQL 发行版提供了一个可在两个级别访问的密钥环接口:
-
在 SQL 级别,作为一组可加载函数,每个函数映射到对服务例程的调用。
-
作为 C 语言接口,可作为服务器插件或可加载函数的插件服务调用。
本节描述如何使用密钥环服务函数在 MySQL 密钥环中存储、检索和删除密钥。有关使用函数的 SQL 接口的信息,请参阅 Section 8.4.4.15, “通用密钥环密钥管理函数”。有关一般密钥环信息,请参阅 Section 8.4.4, “MySQL 密钥环”。
密钥环服务使用启用的底层密钥环插件,如果有的话。如果没有启用密钥环插件,密钥环服务调用将失败。
密钥库中的“记录”由数据(密钥本身)和通过该标识符访问密钥的唯一标识符组成。标识符有两部分:
-
key_id:密钥 ID 或名称。以mysql_开头的key_id值由 MySQL Server 保留。 -
user_id:会话有效用户 ID。如果没有用户上下文,此值可以为NULL。该值实际上不必是“用户”;其含义取决于应用程序。实现密钥环函数接口的函数将
CURRENT_USER()的值作为user_id值传递给密钥环服务函数。
密钥环服务功能具有以下共同特点:
-
每个函数成功返回 0,失败返回 1。
-
key_id和user_id参数形成一个唯一组合,指示密钥环中要使用的密钥。 -
key_type参数提供有关密钥的附加信息,例如其加密方法或预期用途。 -
密钥环服务函数将密钥 ID、用户名、类型和值视为二进制字符串,因此比较区分大小写。例如,
MyKey和mykey的 ID 指的是不同的密钥。
这些密钥环服务函数可用:
-
my_key_fetch()从密钥环中解密并检索密钥,以及其类型。该函数为用于存储返回的密钥和密钥类型的缓冲区分配内存。当不再需要时,调用者应将内存清零或混淆,然后释放它。
语法:
bool my_key_fetch(const char *key_id, const char **key_type, const char* user_id, void **key, size_t *key_len)参数:
-
key_id、user_id:作为一对的以空字符结尾的字符串,形成一个唯一标识符,指示要获取哪个密钥。 -
key_type:缓冲区指针的地址。函数将一个指向提供有关密钥的附加信息的以空字符结尾的字符串的指针存储到其中(在添加密钥时存储)。 -
key:缓冲区指针的地址。函数将一个指向包含获取的密钥数据的缓冲区的指针存储到其中。 -
key_len:函数将*key缓冲区的字节大小存储到一个变量的地址中。
返回值:
返回 0 表示成功,返回 1 表示失败。
-
-
my_key_generate()生成给定类型和长度的新随机密钥,并将其存储在密钥环中。密钥的长度为
key_len,与从key_id和user_id形成的标识符相关联。类型和长度值必须与底层密钥环插件支持的值一致。请参阅第 8.4.4.13 节,“支持的密钥环密钥类型和长度”。语法:
bool my_key_generate(const char *key_id, const char *key_type, const char *user_id, size_t key_len)参数:
-
key_id,user_id:作为一对形成密钥的唯一标识符的以空字符结尾的字符串。 -
key_type:一个以空字符结尾的字符串,提供有关密钥的附加信息。 -
key_len:要生成的密钥的字节大小。
返回值:
返回 0 表示成功,返回 1 表示失败。
-
-
my_key_remove()从密钥环中移除一个密钥。
语法:
bool my_key_remove(const char *key_id, const char* user_id)参数:
key_id,user_id:作为一对形成要移除的密钥的唯一标识符的以空字符结尾的字符串。
返回值:
返回 0 表示成功,返回 1 表示失败。
-
my_key_store()对密钥进行混淆并存储在密钥环中。
语法:
bool my_key_store(const char *key_id, const char *key_type, const char* user_id, void *key, size_t key_len)参数:
-
key_id,user_id:作为一对形成要存储的密钥的唯一标识符的以空字符结尾的字符串。 -
key_type:一个以空字符结尾的字符串,提供有关密钥的附加信息。 -
key:包含要存储的密钥数据的缓冲区。 -
key_len:key缓冲区的字节大小。
返回值:
返回 0 表示成功,返回 1 表示失败。
-
7.7 MySQL 服务器可加载函数
原文:
dev.mysql.com/doc/refman/8.0/en/server-loadable-functions.html
7.7.1 安装和卸载可加载函数
7.7.2 获取有关可加载函数的信息
MySQL 支持可加载函数,即不是内置的函数,但可以在运行时(在启动期间或稍后)加载以扩展服务器功能,或卸载以移除功能。有关可加载函数的可用性描述,请参见第 14.2 节,“可加载函数参考”。可加载函数与内置(本地)函数形成对比,后者作为服务器的一部分实现并始终可用;有关表格,请参见第 14.1 节,“内置函数和运算符参考”。
注意
可加载函数以前被称为用户定义函数(UDFs)。那个术语有点不准确,因为“用户定义”也可以应用于其他类型的函数,例如存储函数(使用 SQL 编写的一种存储对象类型)和通过修改服务器源代码添加的本地函数。
MySQL 发行版包括实现这些服务器功能的可加载函数的部分或全部功能:
-
组复制使您能够在一组 MySQL 服务器实例之间创建高可用的分布式 MySQL 服务,具有数据一致性、冲突检测和解决以及内置的组成员服务。请参见第二十章,“组复制”。
-
MySQL 企业版包括基于 OpenSSL 库执行加密操作的函数。请参见第 8.6 节,“MySQL 企业加密”。
-
MySQL 企业版包括提供 SQL 级 API 用于掩码和去标识化操作的函数。请参见 MySQL 企业数据掩码和去标识化元素。
-
MySQL 企业版包括用于监视和记录连接和查询活动的审计日志功能。请参见第 8.4.5 节,“MySQL 企业审计”,以及第 8.4.6 节,“审计消息组件”。
-
MySQL 企业版包括实现应用级防火墙的防火墙功能,以使数据库管理员能够根据匹配接受语句的模式允许或拒绝 SQL 语句执行。请参见第 8.4.7 节,“MySQL 企业防火墙”。
-
查询重写器检查 MySQL Server 收到的语句,并在服务器执行之前可能对其进行重写。请参阅第 7.6.4 节,“重写器查询重写插件”
-
版本令牌使得可以创建并围绕服务器令牌进行同步,应用程序可以使用这些令牌来防止访问不正确或过时的数据。请参阅第 7.6.6 节,“版本令牌”。
-
MySQL Keyring 为敏感信息提供了安全存储。请参阅第 8.4.4 节,“MySQL Keyring”。
-
锁定服务为应用程序提供了一个锁定接口。请参阅第 7.6.9.1 节,“锁定服务”。
-
函数提供了访问查询属性的接口。请参阅第 11.6 节,“查询属性”。
以下各节描述了如何安装和卸载可加载函数,以及如何在运行时确定已安装哪些可加载函数并获取有关它们的信息。
在某些情况下,可加载函数是通过安装实现该函数的组件来加载的,而不是直接加载函数。有关特定可加载函数的详细信息,请参阅包含该函数的服务器功能的安装说明。
有关编写可加载函数的信息,请参阅向 MySQL 添加函数。
7.7.1 安装和卸载可加载函数
如其名称所示,可加载函数必须在服务器中加载后才能使用。MySQL 支持在服务器启动期间自动加载函数以及随后的手动加载。
在加载可加载函数时,有关其的信息可如第 7.7.2 节“获取有关可加载函数的信息”所述获得。
-
安装可加载函数
-
卸载可加载函数
-
重新安装或升级可加载函数
安装可加载函数
要手动加载可加载函数,请使用CREATE FUNCTION语句。例如:
CREATE FUNCTION metaphon
RETURNS STRING
SONAME 'udf_example.so';
文件基本名称取决于您的平台。Unix 和类 Unix 系统的常见后缀是.so,Windows 的是.dll。
CREATE FUNCTION具有以下效果:
-
它将函数加载到服务器中,使其立即可用。
-
它在
mysql.func系统表中注册函数,使其在服务器重新启动时保持持久性。因此,CREATE FUNCTION需要对mysql系统数据库的INSERT权限。 -
它将函数添加到性能模式
user_defined_functions表中,该表提供有关已安装可加载函数的运行时信息。参见第 7.7.2 节“获取有关可加载函数的信息”。
可加载函数的自动加载发生在正常服务器启动序列期间:
-
在
mysql.func表中注册的函数已安装。 -
在启动时安装的组件或插件可能会自动安装相关函数。
-
自动函数安装将函数添加到性能模式
user_defined_functions表中,该表提供有关已安装函数的运行时信息。
如果服务器使用--skip-grant-tables选项启动,则mysql.func表中注册的函数不会被加载,也无法使用。这不适用于组件或插件自动安装的函数。
卸载可加载函数
要删除可加载函数,请使用DROP FUNCTION语句。例如:
DROP FUNCTION metaphon;
DROP FUNCTION有以下影响:
-
它会卸载函数使其不可用。
-
它会从
mysql.func系统表中删除函数。因此,DROP FUNCTION需要对mysql系统数据库的DELETE权限。由于函数不再在mysql.func表中注册,服务器在后续重新启动时不会加载该函数。 -
它会从性能模式
user_defined_functions表中删除提供有关已安装可加载函数的运行时信息的函数。
DROP FUNCTION不能用于删除由组件或插件自动安装而不是使用CREATE FUNCTION安装的可加载函数。这样的函数在卸载安装它的组件或插件时也会自动删除。
重新安装或升级可加载函数
要重新安装或升级与可加载函数关联的共享库,请发出DROP FUNCTION语句,升级共享库,然后发出CREATE FUNCTION语句。如果先升级共享库,然后使用DROP FUNCTION,服务器可能会意外关闭。
7.7.2 获取有关可加载函数的信息
原文:
dev.mysql.com/doc/refman/8.0/en/obtaining-loadable-function-information.html
Performance Schema user_defined_functions 表包含当前安装的可加载函数的信息:
SELECT * FROM performance_schema.user_defined_functions;
mysql.func 系统表还列出了已安装的可加载函数,但仅列出使用 CREATE FUNCTION 安装的函数。user_defined_functions 表列出了使用 CREATE FUNCTION 安装的可加载函数,以及由组件或插件自动安装的可加载函数。这种差异使得 user_defined_functions 比 mysql.func 更适合检查已安装的可加载函数。参见 Section 29.12.21.10, “用户定义函数表”。
7.8 在一台机器上运行多个 MySQL 实例
7.8.1 设置多个数据目录
7.8.2 在 Windows 上运行多个 MySQL 实例
7.8.3 在 Unix 上运行多个 MySQL 实例
7.8.4 在多服务器环境中使用客户端程序
在某些情况下,您可能希望在单台机器上运行多个 MySQL 实例。您可能希望在保持现有生产设置不受干扰的同时测试新的 MySQL 发布版。或者您可能希望为不同的用户提供对他们自己管理的不同 mysqld 服务器的访问权限。(例如,您可能是一个希望为不同客户提供独立的 MySQL 安装的互联网服务提供商。)
每个实例可以使用不同的 MySQL 服务器二进制文件,或者对多个实例使用相同的二进制文件,或者两种方法的任意组合。例如,您可以从 MySQL 5.7 运行一个服务器,从 MySQL 8.0 运行另一个服务器,以查看不同版本如何处理给定的工作负载。或者您可以运行当前生产版本的多个实例,每个实例管理不同的数据库集。
无论您是否使用不同的服务器二进制文件,您运行的每个实例都必须配置具有几个操作参数的唯一值。这消除了实例之间冲突的可能性。参数可以在命令行上设置,选项文件中设置,或通过设置环境变量设置。请参见 Section 6.2.2, “指定程序选项”。要查看给定实例使用的值,请连接到该实例并执行 SHOW VARIABLES 语句。
MySQL 实例管理的主要资源是数据目录。每个实例应该使用不同的数据目录,其位置使用 --datadir=*dir_name* 选项指定。有关配置每个实例使用自己的数据目录的方法,以及未能这样做的危险的警告,请参见 Section 7.8.1, “设置多个数据目录”。
除了使用不同的数据目录外,几个其他选项必须为每个服务器实例具有不同的值:
-
--port=*port_num*--port控制 TCP/IP 连接的端口号。或者,如果主机有多个网络地址,您可以设置bind_address系统变量,使每个服务器监听不同的地址。 -
--socket={*file_name*|*pipe_name*}--socket控制 Unix 上的 Unix 套接字文件路径或 Windows 上的命名管道名称。在 Windows 上,仅需要为允许命名管道连接的服务器指定不同的管道名称。 -
--shared-memory-base-name=*name*此选项仅在 Windows 上使用。它指定 Windows 服务器用于允许客户端使用共享内存连接的共享内存名称。仅需要为允许共享内存连接的服务器指定不同的共享内存名称。
-
--pid-file=*file_name*此选项指示服务器写入其进程 ID 的文件的路径名。
如果您使用以下日志文件选项,则它们的值必须对每个服务器不同:
-
--general_log_file=*file_name* -
--slow_query_log_file=*file_name*
有关日志文件选项的进一步讨论,请参见 第 7.4 节,“MySQL 服务器日志”。
为了获得更好的性能,您可以为每个服务器单独指定以下选项,以在几个物理磁盘之间分散负载:
--tmpdir=*dir_name*
拥有不同的临时目录还可以更容易地确定哪个 MySQL 服务器创建了任何给定的临时文件。
如果您在不同位置安装了多个 MySQL 实例,可以使用 --basedir=*dir_name* 选项为每个安装指定基目录。这会导致每个实例自动使用不同的数据目录、日志文件和 PID 文件,因为这些参数的默认值都是相对于基目录的。在这种情况下,您需要指定的其他选项只有 --socket 和 --port 选项。假设您使用 tar 文件二进制发行版安装了不同版本的 MySQL。这些安装在不同的位置,因此您可以在相应的基目录下使用命令 bin/mysqld_safe 启动每个安装的服务器。mysqld_safe 确定要传递给 mysqld 的正确 --basedir 选项,您只需指定给 mysqld_safe 的 --socket 和 --port 选项。
如下节所讨论的,可以通过指定适当的命令选项或设置环境变量来启动额外的服务器。但是,如果您需要更长期地运行多个服务器,最方便的方法是使用选项文件为每个服务器指定那些必须对其唯一的选项值。--defaults-file 选项对此很有用。
7.8.1 设置多个数据目录
原文:
dev.mysql.com/doc/refman/8.0/en/multiple-data-directories.html
机器上的每个 MySQL 实例应该有自己的数据目录。位置是使用--datadir=*dir_name*选项指定的。
有不同的方法来为新实例设置数据目录:
-
创建一个新的数据目录。
-
复制现有数据目录。
以下讨论提供了有关每种方法的更多详细信息。
警告
通常,您不应该有两个更新同一数据库中数据的服务器。如果您的操作系统不支持无故障系统锁定,这可能会导致令人不快的惊喜。如果(尽管有此警告)您运行使用相同数据目录的多个服务器,并且它们启用了日志记录,则必须使用适当的选项来指定每个服务器唯一的日志文件名。否则,服务器会尝试记录到相同的文件。
即使遵守了前面的预防措施,这种设置仅适用于MyISAM和MERGE表,而不适用于任何其他存储引擎。此外,在 NFS 环境中,始终不要在多个服务器之间共享数据目录。允许多个 MySQL 服务器通过 NFS 访问共享数据目录是非常糟糕的想法。主要问题是 NFS 是速度瓶颈。它不适用于这种用途。NFS 的另一个风险是你必须想出一种方法来确保两个或更多服务器不会相互干扰。通常,NFS 文件锁定由lockd守护程序处理,但目前没有平台可以在任何情况下 100%可靠地执行锁定。
创建一个新的数据目录
使用此方法,数据目录的状态与您首次安装 MySQL 时相同,并且具有默认的 MySQL 帐户集和没有用户数据。
在 Unix 上,初始化数据目录。参见第 2.9 节,“安装后设置和测试”。
在 Windows 上,数据目录包含在 MySQL 发行版中:
-
Windows 的 MySQL Zip 存档发行版包含一个未修改的数据目录。您可以将这样的发行版解压缩到临时位置,然后将
data目录复制到您设置新实例的位置。 -
Windows MSI 软件包安装程序创建并设置安装的服务器使用的数据目录,但还创建一个干净的“模板”数据目录,名称为
data,位于安装目录下。使用 MSI 软件包执行安装后,可以复制模板数据目录以设置其他 MySQL 实例。
复制现有数据目录。
使用此方法,数据目录中存在的任何 MySQL 帐户或用户数据都将转移到新的数据目录。
-
停止使用数据目录的现有 MySQL 实例。这必须是一个干净的关闭,以便实例将任何未决更改刷新到磁盘。
-
将数据目录复制到新数据目录应该所在的位置。
-
复制现有实例使用的
my.cnf或my.ini选项文件。这将作为新实例的基础。 -
修改新的选项文件,使得任何指向原数据目录的路径都指向新数据目录。同时,修改任何其他必须在每个实例中唯一的选项,比如 TCP/IP 端口号和日志文件。有关必须在每个实例中唯一的参数列表,请参见第 7.8 节,“在一台机器上运行多个 MySQL 实例”。
-
启动新实例,并告诉它使用新的选项文件。
7.8.2 在 Windows 上运行多个 MySQL 实例
原文:
dev.mysql.com/doc/refman/8.0/en/multiple-windows-servers.html
7.8.2.1 在 Windows 命令行上启动多个 MySQL 实例
7.8.2.2 启动多个 MySQL 实例作为 Windows 服务
您可以通过从命令行手动启动每个具有适当操作参数的服务器,或者通过将多个服务器安装为 Windows 服务并以此方式运行它们,在 Windows 上运行多个服务器。有关从命令行或作为服务运行 MySQL 的一般说明,请参见第 2.3 节,“在 Microsoft Windows 上安装 MySQL”。以下各节描述了如何为每个服务器启动具有不同值的那些必须对每个服务器唯一的选项,例如数据目录。这些选项在第 7.8 节,“在一台机器上运行多个 MySQL 实例”中列出。
原文:
dev.mysql.com/doc/refman/8.0/en/multiple-windows-command-line-servers.html
7.8.2.1 在 Windows 命令行上启动多个 MySQL 实例
从命令行手动启动单个 MySQL 服务器的过程在 Section 2.3.4.6, “Starting MySQL from the Windows Command Line”中有描述。要以这种方式启动多个服务器,可以在命令行或选项文件中指定适当的选项。将选项放在选项文件中更方便,但必须确保每个服务器都有自己的选项集。为此,请为每个服务器创建一个选项文件,并在运行时使用--defaults-file选项告诉服务器文件名。
假设您想要在端口 3307 上运行一个mysqld实例,数据目录为C:\mydata1,另一个实例在端口 3308 上,数据目录为C:\mydata2。使用以下步骤:
-
确保每个数据目录都存在,包括包含授权表的
mysql数据库的副本。 -
创建两个选项文件。例如,创建一个名为
C:\my-opts1.cnf的文件,内容如下:[mysqld] datadir = C:/mydata1 port = 3307创建第二个名为
C:\my-opts2.cnf的文件,内容如下:[mysqld] datadir = C:/mydata2 port = 3308 -
使用
--defaults-file选项启动每个服务器时都使用自己的选项文件:C:\> C:\mysql\bin\mysqld --defaults-file=C:\my-opts1.cnf C:\> C:\mysql\bin\mysqld --defaults-file=C:\my-opts2.cnf每个服务器都在前台运行(直到服务器稍后退出时不会出现新提示),因此您需要在单独的控制台窗口中发出这两个命令。
要关闭服务器,请使用适当的端口号连接到每个服务器:
C:\> C:\mysql\bin\mysqladmin --port=3307 --host=127.0.0.1 --user=root --password shutdown
C:\> C:\mysql\bin\mysqladmin --port=3308 --host=127.0.0.1 --user=root --password shutdown
如上所述配置的服务器允许客户端通过 TCP/IP 连接。如果您的 Windows 版本支持命名管道,并且您还希望允许命名管道连接,请指定启用命名管道的选项并指定其名称。支持命名管道连接的每个服务器必须使用唯一的管道名称。例如,C:\my-opts1.cnf文件可能如下所示:
[mysqld]
datadir = C:/mydata1
port = 3307
enable-named-pipe
socket = mypipe1
类似地修改C:\my-opts2.cnf以供第二个服务器使用。然后按照先前描述的方式启动服务器。
对于希望允许共享内存连接的服务器,也适用类似的过程。通过启动具有启用shared_memory系统变量的服务器,并通过设置shared_memory_base_name系统变量来为每个服务器指定唯一的共享内存名称,启用此类连接。
原文:
dev.mysql.com/doc/refman/8.0/en/multiple-windows-services.html
7.8.2.2 启动多个 MySQL 实例作为 Windows 服务
在 Windows 上,MySQL 服务器可以作为 Windows 服务运行。有关安装、控制和删除单个 MySQL 服务的过程,请参阅 Section 2.3.4.8, “Starting MySQL as a Windows Service”。
要设置多个 MySQL 服务,您必须确保每个实例除了其他必须针对每个实例唯一的参数外,还使用不同的服务名称。
对于以下说明,假设您想从分别安装在C:\mysql-5.7.9和C:\mysql-8.0.36的两个不同版本的 MySQL 运行mysqld服务器。(如果您正在运行 5.7.9 作为生产服务器,但也想使用 8.0.36 进行测试,可能会出现这种情况。)
要将 MySQL 安装为 Windows 服务,请使用--install或--install-manual选项。有关这些选项的信息,请参阅 Section 2.3.4.8, “Starting MySQL as a Windows Service”。
根据前面的信息,您有几种设置多个服务的方法。以下说明描述了一些示例。在尝试任何方法之前,请关闭并删除任何现有的 MySQL 服务。
-
方法 1: 在一个标准选项文件中为所有服务指定选项。为此,为每个服务器使用不同的服务名称。假设您想要使用服务名称
mysqld1运行 5.7.9 mysqld,并使用服务名称mysqld2运行 8.0.36 mysqld。在这种情况下,您可以为 5.7.9 使用[mysqld1]组,为 8.0.36 使用[mysqld2]组。例如,您可以像这样设置C:\my.cnf:# options for mysqld1 service [mysqld1] basedir = C:/mysql-5.7.9 port = 3307 enable-named-pipe socket = mypipe1 # options for mysqld2 service [mysqld2] basedir = C:/mysql-8.0.36 port = 3308 enable-named-pipe socket = mypipe2安装服务如下,使用完整的服务器路径名确保 Windows 为每个服务注册正确的可执行程序:
C:\> C:\mysql-5.7.9\bin\mysqld --install mysqld1 C:\> C:\mysql-8.0.36\bin\mysqld --install mysqld2要启动服务,请使用服务管理器,或使用适当的服务名称使用NET START或SC START:
C:\> SC START mysqld1 C:\> SC START mysqld2要停止服务,请使用服务管理器,或使用适当的服务名称使用NET STOP或SC STOP:
C:\> SC STOP mysqld1 C:\> SC STOP mysqld2 -
方法 2: 在单独的文件中为每个服务器指定选项,并在安装服务时使用
--defaults-file告诉每个服务器要使用哪个文件。在这种情况下,每个文件应该使用[mysqld]组列出选项。使用这种方法,要为 5.7.9 mysqld指定选项,请创建一个看起来像这样的文件
C:\my-opts1.cnf:[mysqld] basedir = C:/mysql-5.7.9 port = 3307 enable-named-pipe socket = mypipe1对于 8.0.36 版本的mysqld,创建一个名为
C:\my-opts2.cnf的文件,内容如下:[mysqld] basedir = C:/mysql-8.0.36 port = 3308 enable-named-pipe socket = mypipe2安装服务的步骤如下(每个命令单独一行输入):
C:\> C:\mysql-5.7.9\bin\mysqld --install mysqld1 --defaults-file=C:\my-opts1.cnf C:\> C:\mysql-8.0.36\bin\mysqld --install mysqld2 --defaults-file=C:\my-opts2.cnf当将 MySQL 服务器安装为服务并使用
--defaults-file选项时,服务名称必须在选项之前。安装服务后,启动和停止服务的方法与前面的示例相同。
要删除多个服务,请对每个服务使用SC DELETE mysqld_service_name。或者,对每个服务使用mysqld --remove,在--remove选项后指定服务名称。如果服务名称是默认值(MySQL),在使用mysqld --remove时可以省略它。
7.8.3 在 Unix 上运行多个 MySQL 实例
原文:
dev.mysql.com/doc/refman/8.0/en/multiple-unix-servers.html
注意
这里的讨论使用 mysqld_safe 来启动多个 MySQL 实例。对于使用 RPM 发行版的 MySQL 安装,在几个 Linux 平台上,服务器的启动和关闭由 systemd 管理。在这些平台上,mysqld_safe 没有安装,因为它是不必要的。有关使用 systemd 处理多个 MySQL 实例的信息,请参见 Section 2.5.9, “Managing MySQL Server with systemd”。
在 Unix 上运行多个 MySQL 实例的一种方法是使用不同的默认 TCP/IP 端口和 Unix 套接字文件编译不同的服务器,以便每个服务器在不同的网络接口上监听。为每个安装编译不同的基目录还会自动为每个服务器生成单独的编译数据目录、日志文件和 PID 文件位置。
假设现有的 5.7 服务器配置为默认的 TCP/IP 端口号(3306)和 Unix 套接字文件(/tmp/mysql.sock)。要配置一个新的 8.0.36 服务器具有不同的操作参数,可以使用类似以下的 CMake 命令:
$> cmake . -DMYSQL_TCP_PORT=*port_number* \
-DMYSQL_UNIX_ADDR=*file_name* \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql-8.0.36
这里,port_number 和 file_name 必须与默认的 TCP/IP 端口号和 Unix 套接字文件路径名不同,并且 CMAKE_INSTALL_PREFIX 的值应指定一个安装目录,该目录与现有 MySQL 安装所在的目录不同。
如果您有一个 MySQL 服务器在特定端口号上监听,您可以使用以下命令查找它用于几个重要可配置变量的操作参数,包括基目录和 Unix 套接字文件名:
$> mysqladmin --host=*host_name* --port=*port_number* variables
通过该命令显示的信息,您可以知道在配置额外服务器时不应使用哪些选项值。
如果将 localhost 指定为主机名,mysqladmin 默认使用 Unix 套接字文件而不是 TCP/IP。要明确指定传输协议,请使用 --protocol={TCP|SOCKET|PIPE|MEMORY} 选项。
您无需编译一个新的 MySQL 服务器只是为了使用不同的 Unix 套接字文件和 TCP/IP 端口号开始。也可以使用相同的服务器二进制文件,并在运行时使用不同的参数值启动每个调用。一种方法是使用命令行选项:
$> mysqld_safe --socket=*file_name* --port=*port_number*
要启动第二个服务器,请提供不同的--socket 和 --port 选项值,并通过--datadir=*dir_name* 选项传递给 mysqld_safe,以便服务器使用不同的数据目录。
或者,将每个服务器的选项放在不同的选项文件中,然后使用--defaults-file 选项启动每个服务器,该选项指定适当选项文件的路径。例如,如果两个服务器实例的选项文件分别命名为 /usr/local/mysql/my.cnf 和 /usr/local/mysql/my.cnf2,则可以这样启动服务器:命令:
$> mysqld_safe --defaults-file=/usr/local/mysql/my.cnf
$> mysqld_safe --defaults-file=/usr/local/mysql/my.cnf2
实现类似效果的另一种方法是使用环境变量设置 Unix 套接字文件名和 TCP/IP 端口号:
$> MYSQL_UNIX_PORT=/tmp/mysqld-new.sock
$> MYSQL_TCP_PORT=3307
$> export MYSQL_UNIX_PORT MYSQL_TCP_PORT
$> bin/mysqld --initialize --user=mysql
$> mysqld_safe --datadir=/path/to/datadir &
这是一个快速启动第二个用于测试的服务器的方法。这种方法的好处是环境变量设置适用于从同一 shell 中调用的任何客户端程序。因此,这些客户端的连接会自动定向到第二个服务器。
Section 6.9, “环境变量” 包括了您可以使用来影响 MySQL 程序的其他环境变量列表。
在 Unix 系统上,mysqld_multi 脚本提供了另一种启动多个服务器的方式。请参阅 Section 6.3.4, “mysqld_multi — 管理多个 MySQL 服务器”。
7.8.4 在多服务器环境中使用客户端程序
原文:
dev.mysql.com/doc/refman/8.0/en/multiple-server-clients.html
要连接到一个 MySQL 服务器的客户端程序,该服务器监听的网络接口与编译到您的客户端的不同,您可以使用以下方法之一:
-
使用
--host=*host_name*--port=*port_number*启动客户端,使用 TCP/IP 连接到远程服务器,使用--host=127.0.0.1--port=*port_number*使用 TCP/IP 连接到本地服务器,或使用--host=localhost--socket=*file_name*连接到本地服务器使用 Unix 套接字文件或 Windows 命名管道。 -
启动客户端时使用
--protocol=TCP以使用 TCP/IP 进行连接,使用--protocol=SOCKET以使用 Unix 套接字文件进行连接,使用--protocol=PIPE以使用命名管道进行连接,或使用--protocol=MEMORY以使用共享内存进行连接。对于 TCP/IP 连接,您可能还需要指定--host和--port选项。对于其他类型的连接,您可能需要指定--socket选项以指定 Unix 套接字文件或 Windows 命名管道名称,或者指定--shared-memory-base-name选项以指定共享内存名称。共享内存连接仅在 Windows 上受支持。 -
在 Unix 上,在启动客户端之前,将
MYSQL_UNIX_PORT和MYSQL_TCP_PORT环境变量设置为指向 Unix 套接字文件和 TCP/IP 端口号。如果您通常使用特定的套接字文件或端口号,您可以将设置这些环境变量的命令放在您的.login文件中,以便每次登录时应用。参见第 6.9 节,“环境变量”。 -
在选项文件的
[client]组中指定默认的 Unix 套接字文件和 TCP/IP 端口号。例如,您可以在 Windows 上使用C:\my.cnf,或在 Unix 上使用您的主目录中的.my.cnf文件。参见第 6.2.2.2 节,“使用选项文件”。 -
在 C 程序中,你可以在
mysql_real_connect()调用中指定套接字文件或端口号参数。你也可以通过调用mysql_options()让程序读取选项文件。参见 C API 基本函数描述。 -
如果你正在使用 Perl 的
DBD::mysql模块,你可以从 MySQL 选项文件中读取选项。例如:$dsn = "DBI:mysql:test;mysql_read_default_group=client;" . "mysql_read_default_file=/usr/local/mysql/data/my.cnf"; $dbh = DBI->connect($dsn, $user, $password);查看第 31.9 节,“MySQL Perl API”。
其他编程接口可能提供类似的功能来读取选项文件。
7.9 调试 MySQL
7.9.1 调试 MySQL 服务器
7.9.2 调试 MySQL 客户端
7.9.3 锁定顺序工具
7.9.4 DBUG 包
本节描述了帮助跟踪 MySQL 中问题的调试技术。
7.9.1 调试 MySQL 服务器
7.9.1.1 为调试编译 MySQL
7.9.1.2 创建跟踪文件
7.9.1.3 使用 WER 与 PDB 创建 Windows 崩溃转储
7.9.1.4 在 gdb 下调试 mysqld
7.9.1.5 使用堆栈跟踪
7.9.1.6 使用服务器日志查找 mysqld 中错误的原因
7.9.1.7 如果遇到表损坏,制作可重现的测试用例
如果您正在使用 MySQL 中非常新的功能,可以尝试使用 --skip-new 选项运行 mysqld(该选项禁用所有新的、潜在不安全的功能)。参见 附录 B.3.3.3,“如果 MySQL 一直崩溃怎么办”。
如果 mysqld 不想启动,请验证您没有干扰设置的 my.cnf 文件!您可以使用 mysqld --print-defaults 检查您的 my.cnf 参数,并通过使用 mysqld --no-defaults ... 来避免使用它们。
如果 mysqld 开始占用 CPU 或内存,或者“挂起”,您可以使用 mysqladmin processlist status 查看是否有人执行需要很长时间的查询。如果遇到性能问题或新客户端无法连接的问题,建议在某个窗口中运行 mysqladmin -i10 processlist status。
命令 mysqladmin debug 会将一些关于正在使用的锁、已使用的内存和查询使用情况的信息转储到 MySQL 日志文件中。这可能有助于解决一些问题。即使您没有为调试编译 MySQL,此命令也会提供一些有用的信息!
如果问题是某些表变得越来越慢,您应该尝试使用 OPTIMIZE TABLE 或 myisamchk 优化表。参见 第七章,MySQL 服务器管理。您还应该使用 EXPLAIN 检查慢查询。
你还应该阅读本手册中针对可能在你的环境中独特的问题的特定于操作系统的部分。参见第 2.1 节,“一般安装指导”。
原文:
dev.mysql.com/doc/refman/8.0/en/compiling-for-debugging.html
7.9.1.1 为调试编译 MySQL
如果你遇到了一些非常具体的问题,你可以尝试调试 MySQL。为此,你必须使用-DWITH_DEBUG=1选项配置 MySQL。你可以通过执行mysqld --help来检查 MySQL 是否已启用调试。如果选项中列出了--debug,则表示已启用调试。mysqladmin ver还会将mysqld版本列为mysql ... --debug。
如果在使用-DWITH_DEBUG=1 CMake 选项配置时,mysqld停止崩溃,那么你可能已经发现了 MySQL 中的编译器错误或定时错误。在这种情况下,你可以尝试使用CMAKE_C_FLAGS和CMAKE_CXX_FLAGS CMake 选项添加-g,而不使用-DWITH_DEBUG=1。如果mysqld崩溃,你至少可以使用gdb附加到它,或者使用gdb在核心文件上找出发生了什么。
当你为调试配置 MySQL 时,会自动启用许多额外的安全检查功能,用于监视mysqld的健康状况。如果发现了“意外”情况,会将条目写入stderr,而这会被mysqld_safe重定向到错误日志!这也意味着,如果你在使用源代码分发时遇到了一些意外问题,你应该首先为 MySQL 配置调试。如果你认为自己发现了一个错误,请按照第 1.5 节“如何报告错误或问题”中的说明操作。
在 Windows MySQL 发行版中,默认情况下,mysqld.exe是使用跟踪文件支持编译的。
7.9.1.2 创建跟踪文件
如果mysqld服务器无法启动或容易崩溃,您可以尝试创建一个跟踪文件来查找问题。
要执行此操作,您必须使用已编译调试支持的mysqld。您可以通过执行 mysqld -V 来检查这一点。如果版本号以 -debug 结尾,则编译时支持跟踪文件。(在 Windows 上,调试服务器的名称为mysqld-debug而不是mysqld。)
在 Unix 上以 /tmp/mysqld.trace 或在 Windows 上以 \mysqld.trace 的方式启动mysqld服务器:
$> mysqld --debug
在 Windows 上,您还应该使用--standalone标志,以便不将mysqld作为服务启动。在控制台窗口中,使用以下命令:
C:\> mysqld-debug --debug --standalone
之后,您可以在第二个控制台窗口中使用 mysql.exe 命令行工具重现问题。您可以使用mysqladmin shutdown停止mysqld服务器。
跟踪文件可能会变得非常大!要生成较小的跟踪文件,您可以使用类似以下的调试选项:
mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace
这仅将最有趣的标签信息打印到跟踪文件中。
如果您提交错误报告,请仅将跟踪文件中指示出错位置的那些行添加到错误报告中。如果找不到错误位置,请打开错误报告并将整个跟踪文件上传到报告中,以便 MySQL 开发人员查看。有关说明,请参见第 1.5 节,“如何报告错误或问题”。
跟踪文件是由 Fred Fish 的 DBUG 软件包制作的。请参见第 7.9.4 节,“DBUG 软件包”。
原文:
dev.mysql.com/doc/refman/8.0/en/making-windows-dumps.html
7.9.1.3 使用 WER 与 PDB 创建 Windows 崩溃转储
程序数据库文件(带有后缀pdb)包含在 MySQL 的ZIP Archive Debug Binaries & Test Suite分发中。这些文件提供了在出现问题时调试 MySQL 安装的信息。这是与标准 MSI 或 Zip 文件分开下载的。
注意
PDB 文件包含在一个名为"ZIP Archive Debug Binaries & Test Suite"的单独文件中。
PDB 文件包含有关mysqld和其他工具的更详细信息,可以创建更详细的跟踪和转储文件。您可以使用这些文件与WinDbg或 Visual Studio 一起调试mysqld。
有关 PDB 文件的更多信息,请参阅Microsoft Knowledge Base Article 121366。有关可用的调试选项的更多信息,请参阅Windows 调试工具。
要使用 WinDbg,要么安装完整的 Windows 驱动程序套件(WDK),要么安装独立版本。
重要
.exe和.pdb文件必须完全匹配(版本号和 MySQL 服务器版本);否则,WinDBG 在尝试加载符号时会报错。
-
要生成一个 minidump
mysqld.dmp,请在my.ini中的[mysqld]部分下启用core-file选项。在进行这些更改后重新启动 MySQL 服务器。 -
创建一个目录来存储生成的文件,例如
c:\symbols -
使用查找 GUI 或命令行确定您的windbg.exe可执行文件的路径,例如:
dir /s /b windbg.exe-- 一个常见的默认路径是C:\Program Files\Debugging Tools for Windows (x64)\windbg.exe -
启动
windbg.exe,并将mysqld.exe、mysqld.pdb、mysqld.dmp和源代码的路径传递给它。或者,从 WinDbg GUI 中传递每个路径。例如:windbg.exe -i "C:\mysql-8.0.36-winx64\bin\"^ -z "C:\mysql-8.0.36-winx64\data\mysqld.dmp"^ -srcpath "E:\ade\mysql_archives\8.0\8.0.36\mysql-8.0.36"^ -y "C:\mysql-8.0.36-winx64\bin;SRV*c:\symbols*http://msdl.microsoft.com/download/symbols"^ -v -n -c "!analyze -vvvvv"注意
Windows 命令行处理器会删除
^字符和换行符,因此请确保空格保持完整。
7.9.1.4 在 gdb 下调试 mysqld
在大多数系统上,你也可以从 gdb 中启动 mysqld 以获取更多信息,如果 mysqld 崩溃。
在 Linux 上,如果你想要调试 mysqld 线程,一些较旧的 gdb 版本必须使用 run --one-thread。在这种情况下,你一次只能有一个线程处于活动状态。
在 gdb 下运行 MySQL 时,NPTL 线程(Linux 上的新线程库)可能会导致问题。一些症状包括:
-
mysqld 在启动过程中挂起(在写入
ready for connections之前)。 -
mysqld 在调用
pthread_mutex_lock()或pthread_mutex_unlock()时崩溃。
在这种情况下,在启动 gdb 之前,你应该在 shell 中设置以下环境变量:
LD_ASSUME_KERNEL=2.4.1
export LD_ASSUME_KERNEL
在 gdb 下运行 mysqld 时,你应该使用 --skip-stack-trace 禁用堆栈跟踪,以便在 gdb 中捕获段错误。
使用 --gdb 选项为 mysqld 安装一个 SIGINT 中断处理程序(用于使用 ^C 停止 mysqld 设置断点),并禁用堆栈跟踪和核心文件处理。
如果你一直在 gdb 下进行大量新连接,那么在 gdb 中不释放旧线程的内存,会导致在 gdb 下调试 MySQL 非常困难。你可以通过将 mysqld 的 thread_cache_size 设置为 max_connections + 1 的值来避免这个问题。在大多数情况下,只需使用 --thread_cache_size=5' 就会有很大帮助!
如果在 Linux 上 mysqld 因 SIGSEGV 信号而崩溃,你可以使用 --core-file 选项启动 mysqld 以获取核心转储文件。这个核心文件可以用来生成回溯,帮助你找出 mysqld 为何崩溃:
$> gdb mysqld core
gdb> backtrace full
gdb> quit
参见 Section B.3.3.3, “What to Do If MySQL Keeps Crashing”。
如果你在 Linux 上使用 gdb,你应该在当前目录中安装一个 .gdb 文件,包含以下信息:
set print sevenbit off
handle SIGUSR1 nostop noprint
handle SIGUSR2 nostop noprint
handle SIGWAITING nostop noprint
handle SIGLWP nostop noprint
handle SIGPIPE nostop
handle SIGALRM nostop
handle SIGHUP nostop
handle SIGTERM nostop noprint
这里是一个调试 mysqld 的示例:
$> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # Do this when mysqld crashes
将上述输出包含在一个 bug 报告中,你可以按照 Section 1.5, “How to Report Bugs or Problems” 中的说明进行报告。
如果 mysqld 卡住了,你可以尝试使用一些系统工具如 strace 或 /usr/proc/bin/pstack 来查看 mysqld 卡在哪里。
strace /tmp/log libexec/mysqld
如果你正在使用 Perl DBI 接口,可以通过使用 trace 方法或设置 DBI_TRACE 环境变量来打开调试信息。
7.9.1.5 使用堆栈跟踪
在一些操作系统上,如果mysqld意外死机,错误日志中会包含堆栈跟踪。您可以使用这个来找出mysqld死机的地方(也许是为什么)。参见 Section 7.4.2,“错误日志”。要获得堆栈跟踪,您不能使用 gcc 的-fomit-frame-pointer选项来编译mysqld。参见 Section 7.9.1.1,“为调试编译 MySQL”。
错误日志中的堆栈跟踪看起来像这样:
mysqld got signal 11;
Attempting backtrace. You can use the following information
to find out where mysqld died. If you see no messages after
this, something went terribly wrong...
stack_bottom = 0x41fd0110 thread_stack 0x40000
mysqld(my_print_stacktrace+0x32)[0x9da402]
mysqld(handle_segfault+0x28a)[0x6648e9]
/lib/libpthread.so.0[0x7f1a5af000f0]
/lib/libc.so.6(strcmp+0x2)[0x7f1a5a10f0f2]
mysqld(_Z21check_change_passwordP3THDPKcS2_Pcj+0x7c)[0x7412cb]
mysqld(_ZN16set_var_password5checkEP3THD+0xd0)[0x688354]
mysqld(_Z17sql_set_variablesP3THDP4ListI12set_var_baseE+0x68)[0x688494]
mysqld(_Z21mysql_execute_commandP3THD+0x41a0)[0x67a170]
mysqld(_Z11mysql_parseP3THDPKcjPS2_+0x282)[0x67f0ad]
mysqld(_Z16dispatch_command19enum_server_commandP3THDPcj+0xbb7[0x67fdf8]
mysqld(_Z10do_commandP3THD+0x24d)[0x6811b6]
mysqld(handle_one_connection+0x11c)[0x66e05e]
如果跟踪的函数名解析失败,跟踪将包含较少信息:
mysqld got signal 11;
Attempting backtrace. You can use the following information
to find out where mysqld died. If you see no messages after
this, something went terribly wrong...
stack_bottom = 0x41fd0110 thread_stack 0x40000
[0x9da402]
[0x6648e9]
[0x7f1a5af000f0]
[0x7f1a5a10f0f2]
[0x7412cb]
[0x688354]
[0x688494]
[0x67a170]
[0x67f0ad]
[0x67fdf8]
[0x6811b6]
[0x66e05e]
较新版本的glibc堆栈跟踪函数也会打印相对于对象的地址。在基于glibc的系统(Linux)上,插件意外退出的跟踪看起来像这样:
plugin/auth/auth_test_plugin.so(+0x9a6)[0x7ff4d11c29a6]
要将相对地址(+0x9a6)翻译成文件名和行号,请使用以下命令:
$> addr2line -fie auth_test_plugin.so 0x9a6
auth_test_plugin
mysql-trunk/plugin/auth/test_plugin.c:65
addr2line实用程序是 Linux 上binutils软件包的一部分。
在 Solaris 上,该过程类似。Solaris 的printstack()已经打印了相对地址:
plugin/auth/auth_test_plugin.so:0x1510
要进行翻译,请使用以下命令:
$> gaddr2line -fie auth_test_plugin.so 0x1510
mysql-trunk/plugin/auth/test_plugin.c:88
Windows 已经打印了地址、函数名和行号:
000007FEF07E10A4 auth_test_plugin.dll!auth_test_plugin()[test_plugin.c:72]
7.9.1.6 使用服务器日志查找mysqld错误原因
在启用了一般查询日志的情况下启动mysqld之前,你应该使用myisamchk检查所有表。参见第七章,MySQL 服务器管理。
如果mysqld死机或挂起,你应该启动启用了一般查询日志的mysqld。参见第 7.4.3 节,“一般查询日志”。当mysqld再次死机时,你可以检查日志文件末尾的查询,看看是哪个查询导致了mysqld死机。
如果使用默认的一般查询日志文件,日志将存储在数据库目录中,文件名为*host_name*.log。在大多数情况下,导致mysqld死机的是日志文件中的最后一个查询,但如果可能的话,你应该通过重新启动mysqld并从mysql命令行工具执行找到的查询来验证这一点。如果这样可以,你还应该测试所有未完成的复杂查询。
你也可以尝试对所有执行时间较长的SELECT语句使用EXPLAIN命令,以确保mysqld正确使用索引。参见第 15.8.2 节,“EXPLAIN 语句”。
通过启用慢查询日志,你可以找到执行时间较长的查询。参见第 7.4.5 节,“慢查询日志”。
如果在错误日志中找到文本mysqld restarted(通常是一个名为*host_name*.err的文件),那么你可能已经找到了导致mysqld失败的查询。如果发生这种情况,你应该使用myisamchk检查所有表(参见第七章,MySQL 服务器管理),并测试 MySQL 日志文件中的查询是否有失败的情况。如果找到这样的查询,首先尝试升级到最新的 MySQL 版本。如果这没有帮助,请报告一个 bug,参见第 1.5 节,“如何报告错误或问题”。
如果你使用myisam_recover_options系统变量启动了mysqld,MySQL 会自动检查并尝试修复MyISAM表,如果它们被标记为'未正确关闭'或'崩溃'。如果发生这种情况,MySQL 会在hostname.err文件中写入一个条目'Warning: Checking table ...',接着是Warning: Repairing table,如果需要修复表。如果你在mysqld在意外死机之前没有出现大量这些错误,那么可能出现了问题,需要进一步调查。参见 Section 7.1.7, “Server Command Options”。
当服务器检测到MyISAM表损坏时,它会将额外信息写入错误日志,例如源文件的名称和行号,以及访问该表的线程列表。例如:Got an error from thread_id=1, mi_dynrec.c:368。这是在错误报告中包含的有用信息。
如果mysqld意外死机,这并不是一个好兆头,但在这种情况下,你不应该调查Checking table...的消息,而是应该尝试找出mysqld为何死机。
原文:
dev.mysql.com/doc/refman/8.0/en/reproducible-test-case.html
7.9.1.7 创建测试用例,如果您遇到表格损坏
以下过程适用于MyISAM表格。有关遇到InnoDB表格损坏时应采取的步骤的信息,请参阅第 1.5 节“如何报告错误或问题”。
如果遇到损坏的MyISAM表格,或者mysqld在一些更新语句后总是失败,您可以通过以下方式测试问题是否可重现:
-
使用mysqladmin shutdown停止 MySQL 守护程序。
-
备份表格以防修复出现问题的极小可能性。
-
使用myisamchk -s database/*.MYI检查所有表格。使用myisamchk -r database/
table.MYI修复任何损坏的表格。 -
备份表格的第二份备份。
-
如果需要更多空间,请删除(或移动)MySQL 数据目录中的任何旧日志文件。
-
启动mysqld并启用二进制日志。如果要找到导致mysqld崩溃的语句,还应该启用常规查询日志。请参阅第 7.4.3 节“常规查询日志”和第 7.4.4 节“二进制日志”。
-
当您遇到崩溃的表格时,停止mysqld服务器。
-
恢复备份。
-
重新启动mysqld服务器,不启用二进制日志。
-
使用mysqlbinlog binary-log-file | mysql重新执行语句。二进制日志保存在 MySQL 数据库目录中,名称为
hostname-bin.*NNNNNN*。 -
如果表格再次损坏或者您可以通过上述命令使mysqld停止运行,那么您已经找到了一个可重现的错误。按照第 1.5 节“如何报告错误或问题”中给出的说明,将表格和二进制日志通过 FTP 上传到我们的错误数据库。如果您是支持客户,您可以使用 MySQL 客户支持中心(
www.mysql.com/support/)通知 MySQL 团队有关问题,并尽快修复。
7.9.2 调试 MySQL 客户端
要能够使用集成的调试包调试 MySQL 客户端,您应该使用-DWITH_DEBUG=1配置 MySQL。参见 Section 2.8.7, “MySQL Source-Configuration Options”。
在运行客户端之前,您应该设置MYSQL_DEBUG环境变量:
$> MYSQL_DEBUG=d:t:O,/tmp/client.trace
$> export MYSQL_DEBUG
这会导致客户端在/tmp/client.trace中生成一个跟踪文件。
如果您在自己的客户端代码中遇到问题,您应该尝试连接到服务器,并使用已知可工作的客户端运行您的查询。通过在调试模式下运行mysql(假设您已经使用调试编译 MySQL)来执行此操作:
$> mysql --debug=d:t:O,/tmp/client.trace
这将为您提供有用的信息,以防您发送错误报告。请参见 Section 1.5, “How to Report Bugs or Problems”。
如果您的客户端在某些看起来“合法”的代码处崩溃,您应该检查您的mysql.h包含文件是否与您的 MySQL 库文件匹配。一个非常常见的错误是在新的 MySQL 库中使用来自旧的 MySQL 安装的旧mysql.h文件。
7.9.3 LOCK_ORDER 工具
MySQL 服务器是一个使用许多内部锁定和与锁相关的原语的多线程应用程序,例如互斥锁,rwlocks(包括 prlocks 和 sxlocks),条件和文件。在服务器内部,锁相关对象的集合随着实现新功能和代码重构以提高性能而改变。与使用锁定原语的任何多线程应用程序一样,当同时持有多个锁时,在执行期间遇到死锁的风险始终存在。对于 MySQL,死锁的影响是灾难性的,会导致完全丧失服务。
从 MySQL 8.0.17 开始,为了启用锁获取死锁检测和确保运行时执行不包含死锁的强制执行,MySQL 支持LOCK_ORDER工具。这使得可以定义锁顺序依赖图作为服务器设计的一部分,并且服务器运行时检查以确保锁获取是无环的,并且执行路径符合图形。
本节提供有关使用LOCK_ORDER工具的信息,但仅在基本水平上。有关完整详情,请参阅 MySQL Server Doxygen 文档中的 Lock Order 部分,网址为dev.mysql.com/doc/index-other.html。
LOCK_ORDER工具旨在用于调试服务器,而非生产使用。
要使用LOCK_ORDER工具,请按照以下步骤进行:
-
从源代码构建 MySQL,并使用
-DWITH_LOCK_ORDER=ONCMake选项进行配置,以便构建包含LOCK_ORDER工具的内容。注意
启用
WITH_LOCK_ORDER选项后,MySQL 构建需要flex程序。 -
要在启用
LOCK_ORDER工具的情况下运行服务器,请在服务器启动时启用lock_order系统变量。还有其他用于LOCK_ORDER配置的系统变量可用。 -
对于 MySQL 测试套件操作,mysql-test-run.pl具有一个
--lock-order选项,用于控制在测试用例执行期间是否启用LOCK_ORDER工具。
以下描述的系统变量配置LOCK_ORDER工具的操作,假设 MySQL 已构建包含LOCK_ORDER工具。主要变量是lock_order,指示是否在运行时启用LOCK_ORDER工具:
-
如果
lock_order被禁用(默认情况下),则其他LOCK_ORDER系统变量不会产生任何影响。 -
如果启用了
lock_order,则其他系统变量配置哪些LOCK_ORDER功能要启用。
注意
通常情况下,应通过使用 --lock-order 选项执行 mysql-test-run.pl 来配置 LOCK_ORDER 工具,并让 mysql-test-run.pl 将 LOCK_ORDER 系统变量设置为适当的值。
所有 LOCK_ORDER 系统变量必须在服务器启动时设置。在运行时,它们的值是可见的,但不能更改。
一些系统变量存在成对出现,例如 lock_order_debug_loop 和 lock_order_trace_loop。对于这样的成对变量,在发生与其关联的条件时,这些变量的区别如下:
-
如果启用了
_debug_变量,则会引发调试断言。 -
如果启用了
_trace_变量,则会将错误打印到日志中。
表 7.8 LOCK_ORDER 系统变量摘要
| 变量名称 | 变量类型 | 变量范围 |
|---|---|---|
| lock_order | 布尔值 | 全局 |
| lock_order_debug_loop | 布尔值 | 全局 |
| lock_order_debug_missing_arc | 布尔值 | 全局 |
| lock_order_debug_missing_key | 布尔值 | 全局 |
| lock_order_debug_missing_unlock | 布尔值 | 全局 |
| lock_order_dependencies | 文件名 | 全局 |
| lock_order_extra_dependencies | 文件名 | 全局 |
| lock_order_output_directory | 目录名 | 全局 |
| lock_order_print_txt | 布尔值 | 全局 |
| lock_order_trace_loop | 布尔值 | 全局 |
| lock_order_trace_missing_arc | 布尔值 | 全局 |
| lock_order_trace_missing_key | 布尔值 | 全局 |
| lock_order_trace_missing_unlock | 布尔值 | 全局 |
| 变量名称 | 变量类型 | 变量范围 |
-
lock_order命令行格式 --lock-order[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 OFF是否在运行时启用
LOCK_ORDER工具。如果禁用了lock_order,则不会影响任何其他LOCK_ORDER系统变量。如果启用了lock_order,则其他系统变量配置哪些LOCK_ORDER功能启用。如果启用了
lock_order,则如果服务器遇到未在锁定顺序图中声明的锁定获取序列,将引发错误。 -
lock_order_debug_loop命令行格式 --lock-order-debug-loop[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_debug_loop范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 OFF当
LOCK_ORDER工具遇到在锁定顺序图中标记为循环的依赖关系时,是否导致调试断言失败。 -
lock_order_debug_missing_arc命令行格式 --lock-order-debug-missing-arc[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_debug_missing_arc范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 OFF当
LOCK_ORDER工具遇到在锁定顺序图中未声明的依赖关系时,是否导致调试断言失败。 -
lock_order_debug_missing_key命令行格式 --lock-order-debug-missing-key[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_debug_missing_key范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 OFF当
LOCK_ORDER工具遇到未正确使用性能模式仪器的对象时,是否导致调试断言失败。 -
lock_order_debug_missing_unlock命令行格式 --lock-order-debug-missing-unlock[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_debug_missing_unlock范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 OFFLOCK_ORDER工具在遇到仍在持有的锁被销毁时是否导致调试断言失败。 -
lock_order_dependencies命令行格式 --lock-order-dependencies=file_name引入版本 8.0.17 系统变量 lock_order_dependencies作用域 全局 动态 否 SET_VAR提示适用否 类型 文件名 默认值 空字符串lock_order_dependencies.txt文件的路径,定义了服务器锁定顺序依赖图。可以指定不使用任何依赖项。在这种情况下,将使用空依赖图。
-
lock_order_extra_dependencies命令行格式 --lock-order-extra-dependencies=file_name引入版本 8.0.17 系统变量 lock_order_extra_dependencies作用域 全局 动态 否 SET_VAR提示适用否 类型 文件名 默认值 空字符串包含额外依赖项的文件路径,用于修改锁定顺序依赖图的主要服务器依赖图。这对于使用额外依赖项描述第三方代码行为很有用,而不是修改
lock_order_dependencies.txt文件本身(这是不鼓励的替代方法)。如果未设置此变量,则不使用辅助文件。
-
lock_order_output_directory命令行格式 --lock-order-output-directory=dir_name���入版本 8.0.17 系统变量 lock_order_output_directory作用域 全局 动态 否 SET_VAR提示适用否 类型 目录名称 默认值 空字符串LOCK_ORDER工具写入其日志的目录。如果未设置此变量,则默认为当前目录。 -
lock_order_print_txt命令行格式 --lock-order-print-txt[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_print_txt作用域 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 OFFLOCK_ORDER工具是否执行锁定顺序图分析并打印文本报告。报告包括检测到的任何锁获取循环。 -
lock_order_trace_loop命令行格式 --lock-order-trace-loop[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_trace_loop作用范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 OFFLOCK_ORDER工具在遇到在锁序图中标记为循环的依赖关系时是否在日志文件中打印跟踪信息。 -
lock_order_trace_missing_arc命令行格式 --lock-order-trace-missing-arc[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_trace_missing_arc作用范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 ONLOCK_ORDER工具在遇到在锁序图中未声明的依赖关系时是否在日志文件中打印跟踪信息。 -
lock_order_trace_missing_key命令行格式 --lock-order-trace-missing-key[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_trace_missing_key作用范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 OFFLOCK_ORDER工具在遇到未正确使用性能模式进行仪表化的对象时是否在日志文件中打印跟踪信息。 -
lock_order_trace_missing_unlock命令行格式 --lock-order-trace-missing-unlock[={OFF|ON}]引入版本 8.0.17 系统变量 lock_order_trace_missing_unlock作用范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 ONLOCK_ORDER工具在遇到一个被销毁但仍被持有的锁时是否在日志文件中打印跟踪信息。
7.9.4 DBUG 包
MySQL 服务器和大多数 MySQL 客户端都是使用由 Fred Fish 最初创建的 DBUG 包编译的。当您为调试配置 MySQL 时,此包使得可以获得程序正在执行的跟踪文件。参见 Section 7.9.1.2, “Creating Trace Files”。
本节总结了在使用带有调试支持的 MySQL 程序时可以在命令行上指定的调试选项的参数值。
DBUG 包可以通过使用 --debug[=*debug_options*] 或 -# [*debug_options*] 选项来调用程序。如果您在不指定 debug_options 值的情况下指定 --debug 或 -# 选项,大多数 MySQL 程序会使用默认值。在 Unix 上,服务器默认值为 d:t:i:o,/tmp/mysqld.trace,在 Windows 上为 d:t:i:O,\mysqld.trace。这个默认值的效果是:
-
d: 启用所有调试宏的输出 -
t: 跟踪函数调用和退出 -
i: 在输出行中添加 PID -
o,/tmp/mysqld.trace,O,\mysqld.trace: 设置调试输出文件。
大多数客户端程序使用默认的 debug_options 值为 d:t:o,/tmp/*program_name*.trace,无论平台如何。
以下是一些示例调试控制字符串,如在 shell 命令行上指定的方式:
--debug=d:t
--debug=d:f,main,subr1:F:L:t,20
--debug=d,input,output,files:n
--debug=d:t:i:O,\\mysqld.trace
对于 mysqld,还可以通过设置 debug 系统变量在运行时更改 DBUG 设置。此变量具有全局和会话值:
mysql> SET GLOBAL debug = '*debug_options*';
mysql> SET SESSION debug = '*debug_options*';
更改全局 debug 值需要足够设置全局系统变量的权限。更改会话 debug 值需要足够设置受限会话系统变量的权限。参见 Section 7.1.9.1, “System Variable Privileges”。
debug_options 值是一个以冒号分隔的字段序列:
field_1:field_2:...:field_*N*
值内的每个字段由一个必需的标志字符组成,可选地前面跟着一个 + 或 - 字符,并可选地后跟着一个逗号分隔的修饰符列表:
[+|-]flag[,modifier,modifier,...,modifier]
以下表描述了允许的标志字符。未识别的标志字符会被静默忽略。
| 标志 | 描述 |
|---|---|
d | 启用当前状态下 DBUG_*XXX* 宏的输出。可以跟随一个关键字列表,仅为具有该关键字的 DBUG 宏启用输出。空关键字列表为所有宏启用输出。在 MySQL 中,常见的调试宏关键字包括 enter、exit、error、warning、info 和 loop。 |
D | 每个调试器输出行后延迟。参数是延迟时间,以秒为单位,取决于机器能力。例如,D,20指定了两秒的延迟。 |
f | 将调试、跟踪和性能分析限制为命名函数列表。空列表启用所有函数。仍然必须给出适当的d或t标志;此标志仅限制它们的操作(如果它们已启用)。 |
F | 为每行调试或跟踪输出标识源文件名。 |
i | 为每行调试或跟踪输出标识具有 PID 或线程 ID 的进程。 |
L | 为每行调试或跟踪输出标识源文件行号。 |
n | 为每行调试或跟踪输出打印当前函数嵌套深度。 |
N | 为每行调试输出编号。 |
o | 重定向调试器输出流到指定文件。默认输出为stderr。 |
O | 类似于o,但文件在每次写入之间真正刷新。在需要时,文件在每次写入之间关闭并重新打开。 |
a | 类似于o,但用于追加打开。 |
A | 类似于O,但用于追加打开。 |
p | 将调试器操作限制为指定的进程。必须使用DBUG_PROCESS宏标识进程,并且匹配列表中的一个进程才会发生调试器操作。 |
P | 为每行调试或跟踪输出打印当前进程名称。 |
r | 推送新状态时,不继承先前状态的函数嵌套级别。当输出从左边距开始时很有用。 |
t | 启用函数调用/退出跟踪行。可以跟随一个列表(仅包含一个修饰符),给出一个数字最大跟踪级别,超过该级别,不会发生任何输出,无论是调试还是跟踪宏。默认是编译时选项。 |
T | 为每行输出打印当前时间戳。 |
| 标志 | 描述 |
前导的+或-字符和修饰符列表用于像d或f这样的标志字符,可以为所有适用的修饰符启用调试操作或仅为其中一些启用:
-
没有前导的
+或-,标志值将准确设置为给定的修饰符列表。 -
以前导的
+或-,列表中的修饰符将被添加到或从当前修饰符列表中减去。
以下示例展示了d标志的工作原理。空的d列表启用了所有调试宏的输出。非空列表仅启用列表中的宏关键字的输出。
这些语句将d值设置为给定的修饰符列表:
mysql> SET debug = 'd';
mysql> SELECT @@debug;
+---------+
| @@debug |
+---------+
| d |
+---------+
mysql> SET debug = 'd,error,warning';
mysql> SELECT @@debug;
+-----------------+
| @@debug |
+-----------------+
| d,error,warning |
+-----------------+
前导的+或-会增加或减去当前d值:
mysql> SET debug = '+d,loop';
mysql> SELECT @@debug;
+----------------------+
| @@debug |
+----------------------+
| d,error,warning,loop |
+----------------------+
mysql> SET debug = '-d,error,loop';
mysql> SELECT @@debug;
+-----------+
| @@debug |
+-----------+
| d,warning |
+-----------+
添加到“启用所有宏”会导致没有变化:
mysql> SET debug = 'd';
mysql> SELECT @@debug;
+---------+
| @@debug |
+---------+
| d |
+---------+
mysql> SET debug = '+d,loop';
mysql> SELECT @@debug;
+---------+
| @@debug |
+---------+
| d |
+---------+
禁用所有已启用的宏会完全禁用d标志:
mysql> SET debug = 'd,error,loop';
mysql> SELECT @@debug;
+--------------+
| @@debug |
+--------------+
| d,error,loop |
+--------------+
mysql> SET debug = '-d,error,loop';
mysql> SELECT @@debug;
+---------+
| @@debug |
+---------+
| |
+---------+
第八章 安全
目录
8.1 一般安全问题
8.1.1 安全指南
8.1.2 保持密码安全
8.1.3 使 MySQL 免受攻击者攻击
8.1.4 与安全相关的 mysqld 选项和变量
8.1.5 如何以普通用户身份运行 MySQL
8.1.6 LOAD DATA LOCAL 的安全注意事项
8.1.7 客户端编程安全指南
8.2 访问控制和帐户管理
8.2.1 帐户用户名和密码
8.2.2 MySQL 提供的权限
8.2.3 授权表
8.2.4 指定帐户名称
8.2.5 指定角色名称
8.2.6 访问控制,第一阶段:连接验证
8.2.7 访问控制,第二阶段:请求验证
8.2.8 添加帐户,分配权限和删除帐户
8.2.9 保留帐户
8.2.10 使用角色
8.2.11 帐户类别
8.2.12 使用部分撤销进行权限限制
8.2.13 权限更改何时生效
8.2.14 分配帐户密码
8.2.15 密码管理
8.2.16 服务器处理过期密码
8.2.17 可插拔认证
8.2.18 多因素认证
8.2.19 代理用户
8.2.20 帐户锁定
8.2.21 设置帐户资源限制
8.2.22 解决连接到 MySQL 的问题
8.2.23 基于 SQL 的帐户活动审计
8.3 使用加密连接
8.3.1 配置 MySQL 使用加密连接
8.3.2 加密连接 TLS 协议和密码
8.3.3 创建 SSL 和 RSA 证书和密钥
8.3.4 通过 SSH 从 Windows 远程连接到 MySQL
8.3.5 重用 SSL 会话
8.4 安全组件和插件
8.4.1 认证插件
8.4.2 连接控制插件
8.4.3 密码验证组件
8.4.4 MySQL 密钥环
8.4.5 MySQL 企业审计
8.4.6 审计消息组件
8.4.7 MySQL 企业防火墙
8.5 MySQL 企业数据脱敏和去标识化
8.5.1 数据脱敏组件与数据脱敏插件
8.5.2 MySQL 企业数据脱敏和去标识化组件
8.5.3 MySQL 企业数据脱敏和去标识化插件
8.6 MySQL 企业加密
8.6.1 MySQL 企业加密安装和升级
8.6.2 配置 MySQL 企业加密
8.6.3 MySQL 企业加密用法和示例
8.6.4 MySQL 企业加密函数参考
8.6.5 MySQL 企业加密组件功能描述
8.6.6 MySQL 企业加密传统功能描述
8.7 SELinux
8.7.1 检查 SELinux 是否已启用
8.7.2 更改 SELinux 模式
8.7.3 MySQL 服务器 SELinux 策略
8.7.4 SELinux 文件上下文
8.7.5 SELinux TCP 端口上下文
8.7.6 SELinux 故障排除
8.8 FIPS 支持
在考虑 MySQL 安装中的安全性时,您应该考虑一系列可能的主题以及它们如何影响您的 MySQL 服务器和相关应用程序的安全性:
-
影响安全性的一般因素。这些包括选择强密码,不向用户授予不必要的特权,通过防止 SQL 注入和数据损坏来确保应用程序安全,等等。请参阅第 8.1 节,“一般安全问题”。
-
安装本身的安全性。您的安装的数据文件、日志文件和所有应用程序文件应受保护,以确保未经授权的方可读取或写入。更多信息,请参阅第 2.9 节,“安装后设置和测试”。
-
数据库系统本身的访问控制和安全性,包括授予对数据库、视图和存储过程的访问权限的用户和数据库,在数据库中使用的视图和存储过程。更多信息,请参阅第 8.2 节,“访问控制和账户管理”。
-
安全相关插件提供的功能。请参阅第 8.4 节,“安全组件和插件”。
-
MySQL 和您系统的网络安全。安全性与为个别用户授予权限有关,但您可能还希望限制 MySQL 仅在 MySQL 服务器主机上本地可用,或者仅在有限的其他主机上可用。
-
确保您对数据库文件、配置文件和日志文件进行了充分和适当的备份。同时确保您有一个恢复解决方案,并测试您能够成功从备份中恢复信息。参见第九章,备份和恢复。
注意
本章中的几个主题也在安全部署指南中有所涉及,该指南提供了部署 MySQL 企业版服务器通用二进制分发版的程序,具有管理 MySQL 安装安全性功能的特点。
8.1 一般安全问题
原文:
dev.mysql.com/doc/refman/8.0/en/general-security-issues.html
8.1.1 安全指南
8.1.2 保护密码安全
8.1.3 使 MySQL 免受攻击的安全措施
8.1.4 与安全相关的 mysqld 选项和变量
8.1.5 如何以普通用户身份运行 MySQL
8.1.6 LOAD DATA LOCAL 的安全注意事项
8.1.7 客户端编程安全指南
本节描述了需要注意的一般安全问题,以及您可以采取哪些措施使您的 MySQL 安装更加安全,以防止遭受攻击或滥用。有关 MySQL 用于设置用户帐户和检查数据库访问权限的访问控制系统的具体信息,请参见第 2.9 节,“安装后设置和测试”。
有关 MySQL 服务器安全问题经常被问到的一些问题的答案,请参见第 A.9 节,“MySQL 8.0 FAQ:安全”。
8.1.1 安全指南
任何在连接到互联网的计算机上使用 MySQL 的人都应该阅读本节,以避免最常见的安全错误。
在讨论安全性时,有必要全面保护整个服务器主机(不仅仅是 MySQL 服务器)免受所有类型的适用攻击:窃听、篡改、回放和拒绝服务。我们在这里不涵盖可用性和容错性的所有方面。
MySQL 基于访问控制列表(ACL)的安全性用于所有用户可能尝试执行的连接、查询和其他操作。还支持 MySQL 客户端和服务器之间的 SSL 加密连接。这里讨论的许多概念并不特定于 MySQL;相同的一般思想适用于几乎所有应用程序。
运行 MySQL 时,请遵循以下准则:
-
绝对不要让任何人(除了 MySQL
root帐户)访问mysql系统数据库中的user表! 这是至关重要的。 -
了解 MySQL 访问权限系统的工作原理(参见 Section 8.2, “Access Control and Account Management”)。使用
GRANT和REVOKE语句控制对 MySQL 的访问。不要授予比必要更多的权限。永远不要向所有主机授予权限。检查清单:
-
尝试
mysql -u root。如果您能够成功连接到服务器而不需要输入密码,任何人都可以以 MySQLroot用户的身份连接到您的 MySQL 服务器并具有完全权限!查看 MySQL 安装说明,特别注意有关设置root密码的信息。参见 Section 2.9.4, “Securing the Initial MySQL Account”。 -
使用
SHOW GRANTS语句检查哪些帐户具有访问权限。然后使用REVOKE语句删除那些不必要的权限。
-
-
不要在数据库中存储明文密码。如果您的计算机受到入侵,入侵者可以获取完整的密码列表并使用它们。相反,使用
SHA2()或其他单向哈希函数并存储哈希值。为了防止使用彩虹表进行密码恢复,不要在明文密码上使用这些函数;相反,选择一些字符串作为盐,并使用哈希(hash(password)+salt)值。
-
假设所有密码都将受到使用已知密码列表进行自动破解尝试以及使用关于您的公开信息进行有针对性猜测的影响。不要选择由容易破解或猜测的项目组成的密码,如字典词、专有名词、体育队名、首字母缩写或众所周知的短语,特别是如果它们与您相关。如果这些以可预测方式使用,则大写字母、数字替换和添加以及特殊字符也无济于事。也不要选择您在任何地方看到过的密码或其变体,即使它被作为强密码的示例呈现。
相反,选择尽可能长且不可预测的密码。这并不意味着组合需要是难以记住和重现的随机字符串,尽管如果您有例如可以生成和填充这样的密码并安全存储它们的密码管理软件,这是一个很好的方法。包含多个单词的短语易于创建、记住和重现,并且比典型用户选择的由单个修改过的单词或可预测字符序列组成的密码安全得多。要创建一个安全的短语密码,请确保其中的单词和其他项目不是已知短语或引语,不按可预测顺序出现,并且最好彼此之间没有任何先前关系。
-
投资于防火墙。这可以保护您免受任何软件中至少 50%的各种利用。将 MySQL 放在防火墙后面或者在一个非军事区(DMZ)中。
检查清单:
-
尝试使用诸如
nmap之类的工具从互联网扫描您的端口。MySQL 默认使用端口 3306。这个端口不应该从不受信任的主机访问。作为检查您的 MySQL 端口是否开放的简单方法,尝试在某个远程机器上运行以下命令,其中*server_host*是您的 MySQL 服务器运行的主机的主机名或 IP 地址:$> telnet *server_host* 3306如果telnet挂起或连接被拒绝,则端口被阻止,这正是您希望的。如果您获得一个连接和一些垃圾字符,则端口是开放的,并且应该在您的防火墙或路由器上关闭,除非您真的有充分理由保持其开放。
-
-
访问 MySQL 的应用程序不应信任用户输入的任何数据,并且应使用适当的防御性编程技术编写。参见第 8.1.7 节,“客户端编程安全指南”。
-
不要在互联网上传输明文(未加密)数据。这些信息对于所有有时间和能力拦截并将其用于自己目的的人都是可访问的。相反,使用诸如 SSL 或 SSH 之类的加密协议。MySQL 支持内部 SSL 连接。另一种技术是使用 SSH 端口转发来创建一个加密(和压缩)通信隧道。
-
学会使用tcpdump和strings工具。在大多数情况下,您可以通过发出类似以下命令的命令来检查 MySQL 数据流是否未加密:
$> tcpdump -l -i eth0 -w - src or dst port 3306 | strings这在 Linux 下运行,并且应该在其他系统下进行小的修改后也能运行。
警告
如果您看不到明文数据,这并不总是意味着信息实际上是加密的。如果您需要高安全性,请咨询安全专家。
8.1.2 保持密码安全
8.1.2.1 最终用户密码安全指南
8.1.2.2 管理员密码安全指南
8.1.2.3 密码和日志记录
MySQL 中存在多种上下文中的密码。以下部分提供指南,使最终用户和管理员能够保持这些密码安全,并避免暴露它们。此外,validate_password 插件可用于强制执行有关可接受密码的策略。请参阅 Section 8.4.3, “密码验证组件”。
原文:
dev.mysql.com/doc/refman/8.0/en/password-security-user.html
8.1.2.1 密码安全的最终用户准则
MySQL 用户应该遵循以下准则来保护密码安全。
当您运行客户端程序连接到 MySQL 服务器时,不建议以暴露给其他用户发现的方式指定密码。您运行客户端程序时可以使用的指定密码的方法在此列出,以及每种方法的风险评估。简而言之,最安全的方法是让客户端程序提示输入密码或在正确保护的选项文件中指定密码。
-
使用mysql_config_editor实用程序,它允许您将身份验证凭据存储在名为
.mylogin.cnf的加密登录路径文件中。稍后,MySQL 客户端程序可以读取该文件以获取连接到 MySQL 服务器的身份验证凭据。请参阅 Section 6.6.7, “mysql_config_editor — MySQL Configuration Utility”。 -
在命令行上使用
--password=*password*或-p*password*选项。例如:$> mysql -u francis -pfrank *db_name*警告
这很方便但不安全。在某些系统上,您的密码会对系统状态程序(如ps)可见,其他用户可以调用这些程序来显示命令行。MySQL 客户端通常在初始化序列期间用零覆盖命令行密码参数。然而,在这个值可见的瞬间仍然存在。此外,在某些系统上,这种覆盖策略是无效的,密码仍然对ps可见。(SystemV Unix 系统和其他系统可能存在这个问题。)
如果您的操作环境设置为在终端窗口的标题栏中显示当前命令,则只要命令正在运行,密码就会保持可见,即使命令已经在窗口内容区域滚动出视野。
-
在命令行上使用
--password或-p选项,不指定密码值。在这种情况下,客户端程序会交互式地请求密码:$> mysql -u francis -p *db_name* Enter password: *********字符表示您输入密码的位置。在输入时不会显示密码。以这种方式输入密码比在命令行上指定密码更安全,因为其他用户看不到密码。然而,这种输入密码的方法只适用于您交互式运行的程序。如果您想从非交互式脚本中调用客户端,那么就没有机会从键盘输入密码。在某些系统上,您甚至可能发现脚本的第一行被读取并解释(错误地)为您的密码。
-
将密码存储在一个选项文件中。例如,在 Unix 上,您可以在主目录的
.my.cnf文件的[client]部分列出您的密码:[client] password=*password*为了保护密码安全,该文件不应该对任何人开放访问,只能由您自己访问。为了确保这一点,将文件访问模式设置为
400或600。例如:$> chmod 600 .my.cnf从命令行命名包含密码的特定选项文件,使用
--defaults-file=*file_name*选项,其中file_name是文件的完整路径名。例如:$> mysql --defaults-file=/home/francis/mysql-optsSection 6.2.2.2, “Using Option Files”详细讨论了选项文件。
在 Unix 系统上,mysql客户端会将执行的语句记录到一个历史文件中(参见 Section 6.5.1.3, “mysql Client Logging”)。默认情况下,该文件名为.mysql_history,并创建在您的主目录中。密码可以以明文形式写入 SQL 语句,比如CREATE USER和ALTER USER,因此如果您使用这些语句,它们会被记录在历史文件中。为了保护这个文件,使用限制性的访问模式,与之前描述的.my.cnf文件相同。
如果您的命令解释器维护一个历史记录,保存命令的任何文件都包含在命令行中输入的 MySQL 密码。例如,bash使用~/.bash_history。任何这样的文件都应该具有限制性的访问模式。
原文:
dev.mysql.com/doc/refman/8.0/en/password-security-admin.html
8.1.2.2 密码安全的管理员准则
数据库管理员应遵循以下准则以保护密码安全。
MySQL 将用户账户的密码存储在mysql.user系统表中。绝对不应该将对该表的访问权限授予任何非管理员账户。
可以设置账户密码过期,以便用户必须重置密码。参见第 8.2.15 节,“密码管理”,以及第 8.2.16 节,“服务器处理过期密码”。
可以使用validate_password插件来强制执行可接受密码的策略。参见第 8.4.3 节,“密码验证组件”。
一个用户如果有权限修改插件目录(plugin_dir系统变量的值)或指定插件目录位置的my.cnf文件,就可以替换插件并修改插件提供的功能,包括认证插件。
应该保护可能写入密码的文件,比如日志文件。参见第 8.1.2.3 节,“密码和日志记录”。
8.1.2.3 密码和日志记录
密码可以以明文形式写入 SQL 语句,例如CREATE USER、GRANT和SET PASSWORD。如果 MySQL 服务器按原样记录这些语句,其中的密码将对任何具有日志访问权限的人可见。
语句记录避免以明文形式写入以下语句的密码:
CREATE USER ... IDENTIFIED BY ...
ALTER USER ... IDENTIFIED BY ...
SET PASSWORD ...
START SLAVE ... PASSWORD = ...
START REPLICA ... PASSWORD = ...
CREATE SERVER ... OPTIONS(... PASSWORD ...)
ALTER SERVER ... OPTIONS(... PASSWORD ...)
这些语句中的密码被重写,以便在写入一般查询日志、慢查询日志和二进制日志的语句文本中不会直接显示。重写不适用于其他语句。特别是,对于引用明文密码的mysql.user系统表的INSERT或UPDATE语句,将按原样记录,因此应避免使用这些语句。(直接修改授权表是不鼓励的。)
对于一般的查询日志,可以通过使用--log-raw选项启动服务器来抑制密码重写。出于安全原因,不建议在生产环境中使用此选项。出于诊断目的,查看服务器接收到的语句的确切文本可能是有用的。
默认情况下,由审计日志插件生成的审计日志文件的内容未加密,可能包含敏感信息,例如 SQL 语句的文本。出于安全原因,审计日志文件应写入仅对 MySQL 服务器和有合法查看日志原因的用户可访问的目录。参见第 8.4.5.3 节,“MySQL 企业审计安全注意事项”。
如果安装了查询重写插件(参见查询重写插件),则服务器接收到的语句可能会被重写。在这种情况下,--log-raw选项会影响语句记录如下:
-
没有
--log-raw,服务器记录由查询重写插件返回的语句。这可能与接收到的语句不同。 -
使用
--log-raw,服务器记录接收到的原始语句。
密码重写的一个影响是,无法解析的语句(例如由于语法错误)不会写入一般查询日志,因为无法确定是否不包含密码。需要记录所有语句(包括出现错误的语句)的用例应使用--log-raw选项,但要注意这也会绕过密码重写。
当期望明文密码时,密码重写仅会发生。对于期望密码哈希值的语法语句,不会进行重写。如果错误地为此类语法提供了明文密码,则密码将被记录为给定的形式,而不进行重写。
为了保护日志文件免受未经授权的暴露,将它们放在一个限制服务器和数据库管理员访问的目录中。如果服务器将日志记录到mysql数据库中的表中,请仅授予数据库管理员对这些表的访问权限。
复制品将复制源服务器的密码存储在它们的连接元数据存储库中,默认情况下是mysql数据库中名为slave_master_info的表。现在已不推荐使用数据目录中的文件作为连接元数据存储库,但仍然可能(参见第 19.2.4 节,“中继日志和复制元数据存储库”)。确保连接元数据存储库只能由数据库管理员访问。将密码存储在连接元数据存储库中的替代方法是使用START REPLICA(或在 MySQL 8.0.22 之前,START SLAVE)或START GROUP_REPLICATION语句指定连接到源的凭据。
使用受限访问模式保护包含日志表或包含密码的日志文件的数据库备份。
8.1.3 使 MySQL 免受攻击者攻击
译文:
dev.mysql.com/doc/refman/8.0/en/security-against-attack.html
当连接到 MySQL 服务器时,应该使用密码。密码不会以明文形式通过连接传输。
所有其他信息都以文本形式传输,可以被能够监视连接的任何人读取。如果客户端和服务器之间的连接经过不受信任的网络,并且您对此感到担忧,您可以使用压缩协议使流量更加难以解密。您还可以使用 MySQL 的内部 SSL 支持使连接更加安全。请参见 Section 8.3, “Using Encrypted Connections”。或者,使用 SSH 在 MySQL 服务器和 MySQL 客户端之间建立加密的 TCP/IP 连接。您可以在www.openssh.org/找到一个开源 SSH 客户端,并在en.wikipedia.org/wiki/Comparison_of_SSH_clients找到开源和商业 SSH 客户端的比较。
要使 MySQL 系统安全,您应该强烈考虑以下建议:
-
要求所有 MySQL 账户都有密码。客户端程序不一定知道运行它的人的身份。对于客户端/服务器应用程序来说,用户可以向客户端程序指定任何用户名是很常见的。例如,任何人都可以使用mysql程序连接为任何其他人,只需通过
mysql -u *other_user* *db_name*来调用,如果*other_user*没有密码。如果所有账户都有密码,使用另一个用户的账户连接就变得更加困难。有关设置密码方法的讨论,请参见 Section 8.2.14, “Assigning Account Passwords”。
-
确保在数据库目录中具有读取或写入权限的唯一 Unix 用户帐户是用于运行mysqld的帐户。
-
永远不要将 MySQL 服务器作为 Unix
root用户运行。这是极其危险的,因为任何具有FILE权限的用户都可以使服务器以root身份创建文件(例如,~root/.bashrc)。为了防止这种情况,mysqld拒绝以root身份运行,除非明确使用--user=root选项指定。mysqld可以(而且应该)作为一个普通的、非特权用户运行。您可以创建一个名为
mysql的单独的 Unix 帐户,以使一切更加安全。仅使用此帐户来管理 MySQL。要将mysqld作为不同的 Unix 用户启动,请在指定服务器选项的my.cnf选项文件的[mysqld]组中添加一个指定用户名称的user选项。例如:[mysqld] user=mysql这将导致服务器作为指定用户启动,无论您是手动启动还是使用mysqld_safe或mysql.server启动。有关更多详细信息,请参见 Section 8.1.5,“如何将 MySQL 作为普通用户运行”。
将mysqld作为
root以外的 Unix 用户运行并不意味着您需要更改user表中的root用户名。MySQL 帐户的用户名与 Unix 帐户的用户名无关。 -
不要将
FILE权限授予非管理员用户。拥有此权限的任何用户都可以以mysqld守护程序的权限在文件系统中的任何位置写入文件。这包括包含实现权限表的文件的服务器数据目录。为了使具有FILE权限的操作更安全一些,使用SELECT ... INTO OUTFILE生成的文件不会覆盖现有文件,并且可以被所有人写入。FILE权限也可以用于读取任何对所有用户可读或对服务器运行的 Unix 用户可访问的文件。有了这个权限,您可以将任何文件读入数据库表中。例如,可以通过使用LOAD DATA将/etc/passwd加载到表中,然后可以使用SELECT显示。为了限制可以读取和写入文件的位置,将
secure_file_priv系统设置为特定目录。请参见 Section 7.1.8,“服务器系统变量”。 -
对二进制日志文件和中继日志文件进行加密。加密有助于保护这些文件和其中可能包含的敏感数据,防止外部攻击者滥用,也防止存储它们的操作系统用户未经授权查看。您可以通过将
binlog_encryption系统变量设置为ON来在 MySQL 服务器上启用加密。有关更多信息,请参见第 19.3.2 节,“加密二进制日志文件和中继日志文件”。 -
不要向非管理员用户授予
PROCESS或SUPER权限。mysqladmin processlist和SHOW PROCESSLIST的输出显示当前正在执行的任何语句的文本,因此任何被允许查看服务器进程列表的用户可能能够看到其他用户发出的语句。mysqld为具有
CONNECTION_ADMIN或SUPER权限的用户保留了额外的连接,以便 MySQLroot用户可以登录并检查服务器活动,即使所有正常连接都在使用中。SUPER权限可用于终止客户端连接,通过更改系统变量的值改变服务器操作,并控制复制服务器。 -
不要允许使用符号链接到表格。 (可以使用
--skip-symbolic-links选项禁用此功能。)如果您以root身份运行mysqld,那么任何具有对服务器数据目录的写访问权限的人都可以删除系统中的任何文件!请参见第 10.12.2.2 节,“在 Unix 上为 MyISAM 表使用符号链接”。 -
存储过程和视图应该按照第 27.6 节,“存储对象访问控制”中讨论的安全准则编写。
-
如果您不信任您的 DNS,应该在授权表中使用 IP 地址而不是主机名。无论如何,您都应该非常小心地创建包含通配符的主机名值的授权表条目。
-
如果您想限制单个帐户允许的连接数,可以通过在mysqld中设置
max_user_connections变量来实现。CREATE USER和ALTER USER语句还支持资源控制选项,用于限制帐户允许使用服务器的范围。请参阅 Section 15.7.1.3, “CREATE USER Statement”和 Section 15.7.1.1, “ALTER USER Statement”。 -
如果插件目录对服务器是可写的,用户可能会使用
SELECT ... INTO DUMPFILE将可执行代码写入目录中的文件。可以通过将plugin_dir设置为服务器只读或将secure_file_priv设置为SELECT可以安全写入的目录来防止这种情况发生。
8.1.4 与安全相关的 mysqld 选项和变量
以下表格显示了影响安全性的mysqld选项和系统变量。有关每个选项的描述,请参见第 7.1.7 节,“服务器命令选项”和第 7.1.8 节,“服务器系统变量”。
表 8.1 安全选项和变量摘要
| 名称 | 命令行 | 选项文件 | 系统变量 | 状态变量 | 变量范围 | 动态 |
|---|---|---|---|---|---|---|
| allow-suspicious-udfs | 是 | 是 | ||||
| automatic_sp_privileges | 是 | 是 | 是 | 全局 | 是 | |
| chroot | 是 | 是 | ||||
| local_infile | 是 | 是 | 是 | 全局 | 是 | |
| safe-user-create | 是 | 是 | ||||
| secure_file_priv | 是 | 是 | 是 | 全局 | 否 | |
| skip-grant-tables | 是 | 是 | ||||
| skip_name_resolve | 是 | 是 | 是 | 全局 | 否 | |
| skip_networking | 是 | 是 | 是 | 全局 | 否 | |
| skip_show_database | 是 | 是 | 是 | 全局 | 否 | |
| 名称 | 命令行 | 选项文件 | 系统变量 | 状态变量 | 变量范围 | 动态 |
8.1.5 如何以普通用户身份运行 MySQL
在 Windows 上,您可以使用普通用户帐户将服务器作为 Windows 服务运行。
在 Linux 上,如果使用 MySQL 存储库或 RPM 软件包进行安装,则应该由本地mysql操作系统用户启动 MySQL 服务器mysqld。使用其他操作系统用户启动不受 MySQL 存储库包含的 init 脚本支持。
在 Unix(或 Linux 使用tar.gz软件包进行安装时),MySQL 服务器mysqld可以由任何用户启动和运行。但是,出于安全原因,您应避免以 Unix root用户身份运行服务器。要将mysqld更改为以普通非特权 Unix 用户*user_name*运行,您必须执行以下操作:
-
如果服务器正在运行,请停止它(使用mysqladmin shutdown)。
-
更改数据库目录和文件,以便*
user_name*有权限在其中读取和写入文件(您可能需要以 Unixroot用户的身份执行此操作):$> chown -R *user_name* */path/to/mysql/datadir*如果不这样做,服务器在以*
user_name*运行时无法访问数据库或表。如果 MySQL 数据目录中的目录或文件是符号链接,则
chown -R可能不会为您跟随符号链接。如果没有,请您也必须跟随这些链接并更改它们指向的目录和文件。 -
以用户*
user_name启动服务器。另一种选择是以 Unixroot用户启动mysqld,并使用--user=*user_name*选项。mysqld启动后,然后在接受任何连接之前切换为以 Unix 用户user_name*运行。 -
要在系统启动时自动以给定用户启动服务器,请通过在
/etc/my.cnf选项文件的[mysqld]组或服务器数据目录中的my.cnf选项文件中添加user选项来指定用户名。例如:[mysqld] user=*user_name*
如果您的 Unix 机器本身没有受到保护,您应该在授权表中为 MySQL root帐户分配密码。否则,任何在该机器上具有登录帐户的用户都可以使用--user=root选项运行mysql客户端并执行任何操作。(在任何情况下为 MySQL 帐户分配密码都是个好主意,但特别是在服务器主机上存在其他登录帐户时更是如此。)请参见 Section 2.9.4, “Securing the Initial MySQL Account”。
8.1.6 LOAD DATA LOCAL的安全考虑
原文:
dev.mysql.com/doc/refman/8.0/en/load-data-local-security.html
LOAD DATA语句将数据文件加载到表中。该语句可以加载位于服务器主机上的文件,或者如果指定了LOCAL关键字,则可以加载位于客户端主机上的文件。
LOAD DATA的LOCAL版本存在两个潜在的安全问题:
-
因为
LOAD DATA LOCAL是一个 SQL 语句,解析发生在服务器端,并且文件从客户端主机传输到服务器主机是由 MySQL 服务器发起的,MySQL 服务器告诉客户端语句中命名的文件。理论上,一个经过修补的服务器可以告诉客户端程序传输服务器选择的文件,而不是语句中命名的文件。这样的服务器可以访问客户端用户具有读取访问权限的任何文件。(事实上,一个经过修补的服务器实际上可以对任何语句回复文件传输请求,而不仅仅是LOAD DATA LOCAL,因此更根本的问题是客户端不应连接到不受信任的服务器。) -
在 Web 环境中,客户端是从 Web 服务器连接的,用户可以使用
LOAD DATA LOCAL读取 Web 服务器进程具有读取访问权限的任何文件(假设用户可以对 SQL 服务器运行任何语句)。在这种环境中,客户端实际上是 Web 服务器,而不是由连接到 Web 服务器的用户运行的远程程序。
为了避免连接到不受信任的服务器,客户端可以通过使用--ssl-mode=VERIFY_IDENTITY选项和适当的 CA 证书建立安全连接并验证服务器身份。要实现这种级别的验证,您必须首先确保服务器的 CA 证书可靠地可供副本使用,否则将导致可用性问题。有关更多信息,请参见加密连接的命令选项。
为了避免LOAD DATA问题,客户端应避免使用LOCAL,除非已采取适当的客户端端预防措施。
为了控制本地数据加载,MySQL 允许启用或禁用该功能。此外,从 MySQL 8.0.21 开始,MySQL 使客户端能够将本地数据加载操作限制为位于指定目录中的文件。
-
启用或禁用本地数据加载功能
-
限制本地数据加载的文件
-
MySQL Shell 和本地数据加载
启用或禁用本地数据加载功能
管理员和应用程序可以配置是否允许本地数据加载如下:
-
在服务器端:
-
local_infile系统变量控制服务器端的LOCAL功能。根据local_infile设置,服务器拒绝或允许请求本地数据加载的客户端的本地数据加载。 -
默认情况下,
local_infile被禁用。(这是与 MySQL 先前版本的更改。)为了使服务器明确拒绝或允许LOAD DATA LOCAL语句(无论客户端程序和库在构建时或运行时如何配置),请使用禁用或启用local_infile启动mysqld。local_infile也可以在运行时设置。
-
-
在客户端:
-
ENABLED_LOCAL_INFILECMake选项控制 MySQL 客户端库的编译默认LOCAL功能(参见 Section 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]选项。 -
如果您在读取选项文件中的
[client]组的 Perl 脚本或其他程序中使用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 8.0.21,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数据加载是启用还是禁用的:
-
如果通过默认在 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值的解释如下:-
如果该值为空指针(默认值),则不指定任何目录,结果是不允许任何文件进行
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应准备本地临时文件的目录。因为其他进程可以将文件写入默认的系统特定目录,建议指定
--local-load选项给mysqlbinlog,以指定不同的目录用于数据文件,然后通过在处理来自mysqlbinlog的输出时指定--load-data-local-dir选项给mysql来指定相同的目录。
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 基础设施对象存储流、MySQL HeatWave 服务兼容性检查和修改,并能够进行干跑以在继续进行转储之前识别问题。
转储加载实用程序 util.loadDump()
使用 MySQL Shell 的实例、模式或表转储实用程序创建的转储文件导入到 MySQL HeatWave 服务 DB 系统或 MySQL 服务器实例中。该实用程序管理上传过程,并提供从远程存储的数据流、表或表块的并行加载、进度状态跟踪、恢复和重置功能,以及在转储仍在进行时进行并发加载的选项。MySQL Shell 的并行表导入实用程序可以与转储加载实用程序结合使用,在将数据上传到目标 MySQL 实例之前修改数据。
有关实用程序的详细信息,请参见 MySQL Shell 实用程序。
8.1.7 客户端编程安全准则
原文:
dev.mysql.com/doc/refman/8.0/en/secure-client-programming.html
访问 MySQL 的客户端应用程序应遵循以下准则,以避免错误解释外部数据或暴露敏感信息。
-
正确处理外部数据
-
正确处理 MySQL 错误消息
正确处理外部数据
访问 MySQL 的应用程序不应信任用户输入的任何数据,用户可以尝试通过在网络表单、URL 或您构建的任何应用程序中输入特殊或转义字符序列来欺骗您的代码。确保如果用户尝试通过在表单中输入类似;删除数据库 mysql;的内容来执行 SQL 注入,您的应用程序仍然保持安全。这是一个极端的例子,但如果您不为此做好准备,可能会发生大规模的安全漏洞和数据丢失。
一个常见的错误是仅保护字符串数据值。请记得检查数值数据。如果一个应用程序生成类似SELECT * FROM table WHERE ID=234的查询,当用户输入值234时,用户可以输入值234 OR 1=1来导致应用程序生成查询SELECT * FROM table WHERE ID=234 OR 1=1。结果,服务器检索表中的每一行。这暴露了每一行并导致服务器负载过大。保护免受此类攻击的最简单方法是在数值常量周围使用单引号:SELECT * FROM table WHERE ID='234'。如果用户输入额外信息,它都将成为字符串的一部分。在数值上下文中,MySQL 会自动将此字符串转换为数字并剥离其中的任何尾随非数字字符。
有时人们认为如果数据库只包含公开可用的数据,则无需保护。这是不正确的。即使可以显示数据库中的任何行,您仍应防范拒绝服务攻击(例如,基于前一段中导致服务器浪费资源的技术)。否则,您的服务器将对合法用户不响应。
检查清单:
-
启用严格的 SQL 模式,告诉服务器更严格地接受哪些数据值。请参阅第 7.1.11 节,“服务器 SQL 模式”。
-
尝试在所有的网络表单中输入单引号和双引号(
'和")。如果出现任何 MySQL 错误,请立即调查问题。 -
尝试通过向动态 URL 添加
%22(")、%23(#)和%27(')来修改它们。 -
尝试将动态 URL 中的数据类型从数字类型修改为字符类型,使用前面示例中显示的字符。您的应用程序应对这些攻击和类似攻击保持安全。
-
尝试在数字字段中输入字符、空格和特殊符号而不是数字。您的应用程序应在传递给 MySQL 之前将它们删除,否则会生成错误。将未经检查的值传递给 MySQL 非常危险!
-
在将数据传递给 MySQL 之前检查数据的大小。
-
让应用程序使用与您用于管理目的不同的用户名连接到数据库。不要给予应用程序任何不需要的访问权限。
许多应用程序编程接口提供了一种方法来转义数据值中的特殊字符。正确使用可以防止应用程序用户输入导致应用程序生成具有不同效果的语句:
-
MySQL SQL 语句:使用 SQL 预处理语句,并仅通过占位符接受数据值;参见 第 15.5 节,“预处理语句”。
-
MySQL C API:使用
mysql_real_escape_string_quote()API 调用。或者,使用 C API 预处理语句接口,并仅通过占位符接受数据值;参见 C API 预处理语句接口。 -
MySQL++:对查询流使用
escape和quote修饰符。 -
PHP:使用
mysqli或pdo_mysql扩展,而不是旧的ext/mysql扩展。首选的 API 支持改进的 MySQL 认证协议和密码,以及带有占位符的预处理语句。另请参阅 MySQL 和 PHP。如果必须使用旧的
ext/mysql扩展,则用mysql_real_escape_string_quote()函数进行转义,而不是mysql_escape_string()或addslashes(),因为只有mysql_real_escape_string_quote()是字符集感知的;在使用(无效的)多字节字符集时,其他函数可能会被“绕过”。 -
Perl DBI:使用占位符或
quote()方法。 -
Java JDBC:使用
PreparedStatement对象和占位符。
其他编程接口可能具有类似的功能。
适当处理 MySQL 错误消息
应用程序有责任拦截由执行与 MySQL 数据库服务器的 SQL 语句导致的错误,并适当处理这些错误。
MySQL 错误返回的信息并非毫无意义,因为这些信息对于使用应用程序调试 MySQL 至关重要。例如,要调试一个常见的 10 路连接SELECT语句,如果不提供涉及问题的数据库、表和其他对象的信息,几乎是不可能的。因此,MySQL 错误有时必须包含对这些对象名称的引用。
当应用程序从 MySQL 接收到这样的错误时,一个简单但不安全的方法是拦截并将其原样显示给客户端。然而,揭示错误信息是一种已知的应用程序漏洞类型(CWE-209),应用程序开发人员必须确保应用程序没有这种漏洞。
例如,一个显示如下消息的应用程序向客户端暴露了数据库名称和表名称,这是客户端可能会尝试利用的信息:
ERROR 1146 (42S02): Table 'mydb.mytable' doesn't exist
相反,当应用程序从 MySQL 接收到这样的错误时,正确的行为是记录适当的信息,包括错误信息,仅供信任人员访问的安全审计位置。应用程序可以向用户返回更通用的信息,比如“内部错误”。