Spec-Zone .ru
спецификации, руководства, описания, API
|
Определенные функции не тиражируются хорошо при некоторых условиях:
USER()
, CURRENT_USER()
(или CURRENT_USER
), UUID()
, VERSION()
, и LOAD_FILE()
функции тиражируются без изменения и таким образом не
работают достоверно над ведомым устройством, если построчная репликация не включается. (См. Раздел
16.1.2, "Форматы Репликации".)
USER()
и CURRENT_USER()
автоматически тиражируются, используя построчную
репликацию при использовании MIXED
режим, и генерирует предупреждение в
STATEMENT
режим. (См. также Раздел
16.4.1.7, "Репликация CURRENT_USER()
".) Это - также
истина для VERSION()
и RAND()
.
Для NOW()
, двоичный журнал включает метку времени. Это означает, что значение
как возвращено звонком в эту функцию на ведущем устройстве
тиражируется в ведомое устройство. Это может привести к возможно неожиданному результату, тиражируясь
между серверами MySQL в различных часовых поясах. Предположите, что ведущее устройство располагается в
Нью-Йорке, ведомое устройство располагается в Стокгольме, и оба сервера используют местное время.
Предположите далее, что на ведущем устройстве Вы составляете таблицу mytable
, выполните INSERT
оператор на этой таблице, и затем выбирает из таблицы, как
показано здесь:
mysql>CREATE TABLE mytable (mycol TEXT);
Query OK, 0 rows affected (0.06 sec)mysql>INSERT INTO mytable VALUES ( NOW() );
Query OK, 1 row affected (0.00 sec)mysql>SELECT * FROM mytable;
+---------------------+| mycol |+---------------------+| 2009-09-01 12:00:00 |+---------------------+1 row in set (0.00 sec)
Местное время в Стокгольме на 6 часов позже чем в Нью-Йорке; так, если Вы выходите SELECT NOW()
на ведомом устройстве в этом точном тот же самый момент,
значение 2009-09-01 18:00:00
возвращается. Поэтому, если Вы выбираете
из копии ведомого устройства mytable
после CREATE TABLE
и INSERT
операторы, только показанные, были тиражированы, Вы могли
бы ожидать mycol
содержать значение 2009-09-01
18:00:00
. Однако, дело обстоит не так; когда Вы выбираете из копии ведомого устройства
mytable
, Вы получаете точно тот же самый результат как на ведущем
устройстве:
mysql> SELECT * FROM
mytable;
+---------------------+| mycol |+---------------------+| 2009-09-01 12:00:00 |+---------------------+1 row in set (0.00 sec)
В отличие от этого NOW()
, SYSDATE()
функция не безопасна от репликации, потому что ею не влияют
SET TIMESTAMP
операторы в двоичном журнале и недетерминированы, если
основанное на операторе журналирование используется. Это не проблема, если основанное на строке
журналирование используется.
Альтернатива должна использовать --sysdate-is-now
опция, чтобы вызвать SYSDATE()
быть псевдонимом для NOW()
. Это должно быть сделано на ведущем устройстве и ведомом
устройстве, чтобы работать правильно. В таких случаях предупреждение все еще выпускается этой
функцией, но может безопасно быть проигнорировано пока --sysdate-is-now
используется и на ведущем устройстве и на ведомом
устройстве.
Начинание с MySQL 5.5.1, SYSDATE()
автоматически тиражируется, используя построчную репликацию
при использовании MIXED
режим, и генерирует предупреждение в STATEMENT
режим. (Ошибка #47995)
Следующее ограничение применяется к основанной на
операторе репликации только, не к построчной репликации. GET_LOCK()
, RELEASE_LOCK()
, IS_FREE_LOCK()
, и IS_USED_LOCK()
функции, которые обрабатывают блокировки на уровне
пользователя, тиражируются без ведомого устройства, зная контекст параллелизма на ведущем устройстве.
Поэтому, эти функции не должны использоваться, чтобы вставить в основную таблицу, потому что контент на
ведомом устройстве отличался бы. Например, не делайте заявление такой как INSERT
INTO mytable VALUES(GET_LOCK(...))
.
Начинаясь с MySQL 5.5.1, эти функции автоматически тиражируются, используя построчную репликацию при
использовании MIXED
режим, и генерирует предупреждение в STATEMENT
режим. (Ошибка #47995)
Как обходное решение для предыдущих ограничений, когда основанная на операторе репликация в действительности,
можно использовать стратегию сохранения проблематичного функционального результата в пользовательской переменной
и обращении к переменной в более позднем операторе. Например, следующая единственная строка INSERT
проблематично из-за ссылки на UUID()
функция:
INSERT INTO t VALUES(UUID());
Чтобы работать вокруг проблемы, сделайте это вместо этого:
SET @my_uuid = UUID();INSERT INTO t VALUES(@my_uuid);
Та последовательность операторов тиражируется потому что значение @my_uuid
сохранен
в двоичном журнале как переменное пользователем событие до INSERT
оператор и доступен для использования в INSERT
.
Та же самая идея применяется к многократной строке, вставляет, но является более громоздким, чтобы использовать. Для вставки с двумя строками можно сделать это:
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()
функции
не тиражируются, достоверно используя основанную на операторе репликацию. Обходное решение должно сохранить
результат вызова функции в пользовательской переменной, и затем использовать это в INSERT
оператор. Например, если Вы хотите сохранить результат в названной
таблице mytable
, Вы могли бы обычно делать так как это:
SELECT SQL_CALC_FOUND_ROWS FROM mytable LIMIT 1;INSERT INTO mytable VALUES( FOUND_ROWS() );
Однако, если Вы тиражируетесь mytable
, следует использовать SELECT ... INTO
, и затем сохраните переменную в таблице, как это:
SELECT SQL_CALC_FOUND_ROWS INTO @found_rows FROM mytable LIMIT 1;INSERT INTO mytable VALUES(@found_rows);
Таким образом пользовательская переменная тиражируется как часть контекста, и применяется на ведомое устройство правильно.
Эти функции автоматически тиражируются, используя построчную репликацию при использовании MIXED
режим, и генерирует предупреждение в STATEMENT
режим. (Ошибка #12092, Ошибка
#30244)