某些功能在某些条件下不能很好地复制:
的
用户()
,CURRENT_USER ()
(或CURRENT_USER
),UUID ()
,(版本)
,LOAD_FILE ()
函数被复制而不进行更改,因此除非启用了基于行的复制,否则在副本上不能可靠地工作。(见17.2.1节“复制格式”)。用户()
而且CURRENT_USER ()
使用时使用基于行的复制自动复制混合
模式,并在声明
模式。(见也第17.5.1.8节,CURRENT_USER()的复制)。这对(版本)
而且RAND ()
.为
现在()
时,二进制日志包括时间戳。这意味着值由源上此函数的调用返回复制到副本。为了避免在不同时区的MySQL服务器之间复制时出现意外结果,请在源服务器和副本服务器上同时设置时区。有关更多信息,请参见17.5.1.33节“复制和时区”.为了解释在不同时区的服务器之间进行复制时的潜在问题,假设源位于纽约,副本位于斯德哥尔摩,并且两台服务器都使用本地时间。进一步假设,您在源代码上创建了一个表
mytable
,执行插入
语句在这个表上,然后从表中选择,如下所示:创建mytable (mycol TEXT)mysql> INSERT INTO mytable VALUES (NOW());mysql> SELECT * FROM mytable (0.00 sec)+---------------------+ | mycol | +---------------------+ | 2009-09-01 12:00:00 | +---------------------+ 1行集(0.00秒)
斯德哥尔摩当地时间比纽约晚6个小时;所以,如果你发行
现在选择()
在同一时刻的副本上,值2009-09-01 18:00:00
返回。因此,如果从副本的副本中选择mytable
后创建表
而且插入
您可能认为,刚才显示的语句已被复制mycol
要包含值2009-09-01 18:00:00
.然而,事实并非如此;从副本的副本中选择mytable
,得到的结果与源上的结果完全相同:mysql> SELECT * FROM mytable;+---------------------+ | mycol | +---------------------+ | 2009-09-01 12:00:00 | +---------------------+ 1行集(0.00秒)
不像
现在()
,SYSDATE ()
函数不是复制安全的,因为它不受设置时间戳
如果使用基于语句的日志记录,则是不确定的。如果使用基于行的日志记录,这就不是问题。一种替代方法是使用
——sysdate-is-now
引起选项SYSDATE ()
作为…的别名现在()
.这必须在源和副本上执行才能正确工作。在这种情况下,这个函数仍然会发出警告,但是只要——sysdate-is-now
在源和副本上都使用。SYSDATE ()
使用?时自动使用基于行的复制进行复制混合
模式,并在声明
模式。另请参阅17.5.1.33节“复制和时区”.
以下限制仅适用于基于语句的复制,而不适用于基于行的复制。的
GET_LOCK ()
,RELEASE_LOCK ()
,IS_FREE_LOCK ()
,IS_USED_LOCK ()
在复制处理用户级锁的函数时,副本不知道源上的并发上下文。因此,不应该使用这些函数插入源表,因为副本上的内容会有所不同。例如,不要发出这样的语句INSERT INTO mytable VALUES(GET_LOCK(…))
.这些函数在使用时使用基于行的复制自动复制
混合
模式,并在声明
模式。
当基于语句的复制生效时,作为上述限制的解决方法,您可以使用将有问题的函数结果保存在用户变量中并在以后的语句中引用该变量的策略。例如,下面的单行插入
因为提到了UUID ()
功能:
INSERT INTO t VALUES(UUID());
要解决这个问题,可以这样做:
SET @my_uuid = UUID();INSERT INTO t VALUES(@my_uuid)
的值导致语句序列的复制@my_uuid
在二进制日志中作为用户变量事件存储在插入
语句,可用于插入
.
同样的思想也适用于多行插入,但是使用起来更麻烦。对于两行插入,你可以这样做:
SET @my_uuid1 = UUID();@my_uuid2 = UUID();INSERT INTO t VALUES(@my_uuid1),(@my_uuid2);
但是,如果行数很大或未知,则解决方法很难或不可行的。例如,你不能将下面的语句转换为一个给定的用户变量与每一行相关联的语句:
INSERT INTO t2 SELECT UUID(), * FROM t1;
在存储函数中,RAND ()
只要在函数执行期间只调用一次,则正确复制。(您可以将函数执行时间戳和随机数种子视为源和副本上相同的隐式输入。)
的FOUND_ROWS ()
而且ROW_COUNT ()
使用基于语句的复制不能可靠地复制函数。解决方法是将函数调用的结果存储在用户变量中,然后在插入
声明。例如,如果希望将结果存储在名为mytable
,你通常会这样做:
SELECT SQL_CALC_FOUND_ROWS FROM mytable LIMITINSERT INTO mytable VALUES(FOUND_ROWS());
然而,如果你在复制mytable
,你应该使用选择……成
,然后将变量存储在表中,如下所示:
SELECT SQL_CALC_FOUND_ROWS INTO @found_rows FROM mytable LIMIT 1INSERT INTO mytable VALUES(@found_rows)
通过这种方式,用户变量被复制为上下文的一部分,并正确地应用于副本。
这些函数在使用时使用基于行的复制自动复制混合
模式,并在声明
模式。(Bug #12092, Bug #30244)