MySQL Replication中语句的“安全性”,是指语句及其作用是否可以使用基于语句的格式正确复制。如果该陈述为真,我们称该陈述为 安全的;否则,我们将其称为不安全的。
通常,如果语句是确定性的,则它是安全的;如果不是,则它是不安全的。但是,某些非确定性函数 不被认为是不安全的(请参阅 本节后面的非确定性函数不被认为是不安全的)。此外,使用依赖于硬件的浮点数学函数结果的语句始终被认为是不安全的(请参阅 第 16.4.1.12 节,“复制和浮点值”)。
处理安全和不安全的语句。
根据语句是否被认为是安全的,以及相对于二进制日志记录格式(即 的当前值
binlog_format
),对语句进行不同的处理。
使用基于行的日志记录时,安全和不安全语句的处理没有区别。
使用混合格式日志记录时,标记为不安全的语句将使用基于行的格式进行记录;使用基于语句的格式记录被视为安全的语句。
使用基于语句的日志记录时,标记为不安全的语句会为此生成警告。安全语句正常记录。
每个标记为不安全的语句都会生成警告。以前,如果在源上执行大量此类语句,可能会导致错误日志文件过大。为了防止这种情况,MySQL 5.7 提供了警告抑制机制,其表现如下:每当最近的 50
ER_BINLOG_UNSAFE_STATEMENT
条警告在任意 50 秒内产生超过 50 次时,将启用警告抑制。激活后,这会导致此类警告不会写入错误日志;相反,对于这种类型的每 50 个警告,一个注释The
last warning was repeated
被写入错误日志。只要最近 50 次此类警告在 50 秒或更短时间内发出,这种情况就会继续;一旦速率降低到该阈值以下,警告将再次正常记录。警告抑制不会影响如何确定基于语句的日志记录的语句安全性,也不会影响如何将警告发送到客户端。对于每个这样的语句,MySQL 客户端仍然会收到一个警告。
N
times in
last S
seconds
有关详细信息,请参阅第 16.2.1 节,“复制格式”。
语句被认为是不安全的。 具有以下特征的语句被认为是不安全的:
包含可能在副本上返回不同值的系统函数的语句。 这些功能包括
FOUND_ROWS()
,GET_LOCK()
,IS_FREE_LOCK()
,IS_USED_LOCK()
,LOAD_FILE()
,MASTER_POS_WAIT()
,PASSWORD()
,RAND()
,RELEASE_LOCK()
,ROW_COUNT()
,SESSION_USER()
,SLEEP()
,SYSDATE()
,SYSTEM_USER()
,USER()
,UUID()
, 和UUID_SHORT()
。非确定性函数不被认为是不安全的。 尽管这些函数不是确定性的 , 但 出于日志记录 和 复制的 目的
CONNECTION_ID()
, 它们被 视为安全 的 :CURDATE()
、、、、、、、、、、、、、、、、、 和 。CURRENT_DATE()
CURRENT_TIME()
CURRENT_TIMESTAMP()
CURTIME()
LAST_INSERT_ID()
LOCALTIME()
LOCALTIMESTAMP()
NOW()
UNIX_TIMESTAMP()
UTC_DATE()
UTC_TIME()
UTC_TIMESTAMP()
有关详细信息,请参阅 第 16.4.1.15 节,“复制和系统功能”。
对系统变量的引用。 使用基于语句的格式无法正确复制大多数系统变量。请参阅 第 16.4.1.37 节,“复制和变量”。对于例外情况,请参阅第 5.4.4.3 节,“混合二进制日志记录格式”。
可加载函数。 由于我们无法控制可加载函数的作用,我们必须假设它正在执行不安全的语句。
全文插件。 这个插件在不同的 MySQL 服务器上可能表现不同;因此,依赖于它的语句可能会产生不同的结果。出于这个原因,所有依赖全文插件的语句都被视为不安全的(Bug #11756280,Bug #48183)。
触发器或存储程序更新具有 AUTO_INCREMENT 列的表。 这是不安全的,因为更新行的顺序在源和副本上可能不同。
此外,对
INSERT
具有复合主键的表进行AUTO_INCREMENT
操作是不安全的,该主键包含的列不是该复合键的第一列。有关详细信息,请参阅 第 16.4.1.1 节,“复制和 AUTO_INCREMENT”。
在具有多个主键或唯一键的表上插入 ... ON DUPLICATE KEY UPDATE 语句。 当针对包含多个主键或唯一键的表执行时,此语句被认为是不安全的,它对存储引擎检查键的顺序敏感,这不是确定性的,并且选择更新的行MySQL 服务器取决于。
INSERT ... ON DUPLICATE KEY UPDATE
针对具有多个唯一键或主键的表 的 语句被标记为对基于语句的复制不安全。(缺陷 #11765650,缺陷 #58637)使用 LIMIT 更新。 未指定检索行的顺序,因此被认为是不安全的。请参阅 第 16.4.1.17 节,“复制和限制”。
访问或引用日志表。 系统日志表的内容在源和副本之间可能不同。
事务性操作之后的非事务性操作。 在事务中,允许在任何事务性读取或写入之后执行任何非事务性读取或写入被认为是不安全的。
有关详细信息,请参阅 第 16.4.1.33 节,“复制和事务”。
访问或引用自记录表。 所有对自记录表的读写都被认为是不安全的。在事务中,读取或写入自记录表后的任何语句也被认为是不安全的。
加载数据语句。
LOAD DATA
被视为不安全并且当binlog_format=mixed
语句以基于行的格式记录时。与其他不安全语句不同, When 不会生成警告。binlog_format=statement
LOAD DATA
XA 交易。 如果在源上并行提交的两个 XA 事务正在以相反的顺序在副本上准备,则基于语句的复制可能会发生无法安全解析的锁定依赖关系,并且复制可能因副本上的死锁而失败。设置时
binlog_format=STATEMENT
,XA 事务内的 DML 语句被标记为不安全并生成警告。binlog_format=MIXED
设置或 时binlog_format=ROW
,XA 事务内的 DML 语句使用基于行的复制进行记录,并且不存在潜在问题。
有关其他信息,请参阅 第 16.4.1 节,“复制功能和问题”。