Spec-Zone .ru
спецификации, руководства, описания, API
|
Двоичный журнал содержит информацию о SQL-операторах, которые изменяют содержание базы данных. Эта информация хранится в форме "событий", которые описывают модификации. У двоичного журнала есть две важных цели:
Для репликации двоичный журнал используется на главных серверах репликации в качестве записи операторов, которые будут отправлены ведомым серверам. Главный сервер отправляет события, содержавшиеся в его двоичном журнале к его ведомым устройствам, которые выполняют те события, чтобы произвести те же самые изменения данных, которые были сделаны на ведущем устройстве. См. Раздел 16.2, "Реализация Репликации".
Определенные операции восстановления данных требуют использования двоичного журнала. После того, как файл резервной копии был восстановлен, события в двоичном журнале, которые были записаны после того, как резервное копирование было сделано, повторно выполняются. Эти события осовременивают базы данных от точки резервного копирования. См. Раздел 7.3.2, "Используя Резервные копии для Восстановления".
Однако, есть определенные двоичные проблемы журналирования, которые применяются относительно сохраненных программ (хранимые процедуры и функции, триггеры, и события), если журналирование происходит на уровне оператора:
В некоторых случаях возможно, что оператор будет влиять на различные наборы строк на ведущем устройстве и ведомом устройстве.
Тиражированные операторы, выполняемые на ведомом устройстве, обрабатываются ведомым потоком SQL, у которого есть полные полномочия. Для процедуры возможно следовать за различными путями выполнения на основных и ведомых серверах, таким образом, пользователь может записать подпрограмму, содержащую опасный оператор, который выполнится только на ведомом устройстве, где это обрабатывается потоком, у которого есть полные полномочия.
Если сохраненная программа, которая изменяет данные, недетерминирована, это не повторимо. Это может привести к различным данным на ведущем устройстве и ведомом устройстве, или заставить восстановленные данные отличаться от исходных данных.
Этот раздел описывает, как MySQL 5.7 обрабатывает двоичное журналирование для сохраненных программ. Это утверждает текущие положения, которые реализация помещает в использование сохраненных программ, и что можно сделать, чтобы избежать проблем. Это также обеспечивает дополнительную информацию о причинах этих условий.
Вообще, проблемы, описанные здесь, заканчиваются, когда двоичное журналирование происходит на уровне
SQL-оператора. Если Вы используете основанное на строке двоичное журналирование, журнал содержит изменения,
произведенные в отдельных строках в результате выполнения SQL-операторов. Когда подпрограммы или триггеры
выполняются, изменения строки регистрируются, не операторы, которые производят изменения. Для хранимых процедур
это означает что CALL
оператор не регистрируется. Для сохраненных функций изменения строки, произведенные в пределах функции,
регистрируются, не вызов функции. Для триггеров регистрируются изменения строки, произведенные триггером. На
ведомой стороне только изменения строки замечаются, не сохраненный вызов программы. Для получения общей
информации об основанном на строке журналировании, см. Раздел 16.1.2,
"Форматы Репликации".
Если не отмечено иначе, комментарии здесь предполагают, что Вы включили двоичному журналированию, запуская
сервер с --log-bin
опция. (См. Раздел
5.2.4, "Двоичный Журнал".), Если двоичный журнал не включается, репликация не возможна, и при
этом двоичный журнал не доступен для восстановления данных.
Текущие положения на использовании сохраненных функций в MySQL 5.7 могут быть получены в итоге следующим образом. Эти условия не применяются к хранимым процедурам или событиям Event Scheduler, и они не применяются, если двоичное журналирование не включается.
Чтобы создать или изменить сохраненную функцию, Вы должны иметь SUPER
полномочие, в дополнение к CREATE ROUTINE
или ALTER ROUTINE
полномочие, которое обычно требуется. (В зависимости от
DEFINER
значение в функциональном определении, SUPER
мог бы требоваться независимо от того, включается ли двоичное
журналирование. См. Раздел 13.1.12,"CREATE PROCEDURE
и CREATE FUNCTION
Синтаксис"
.)
Когда Вы создаете сохраненную функцию, следует объявить или что это детерминировано или что это не изменяет данные. Иначе, это может быть опасно для восстановления данных или репликации.
По умолчанию, для a CREATE
FUNCTION
оператор, который будет принят, по крайней мере один из DETERMINISTIC
,
NO SQL
, или READS SQL DATA
должен быть
определен явно. Иначе ошибка происходит:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL,or READS SQL DATA in its declaration and binary logging is enabled(you *might* want to use the less safe log_bin_trust_function_creatorsvariable)
Эта функция детерминирована (и не изменяет данные), таким образом, это безопасно:
CREATE FUNCTION f1(i INT)RETURNS INTDETERMINISTICREADS SQL DATABEGIN RETURN i;END;
Эта функция использование UUID()
,
который не детерминирован, таким образом, функция также не детерминирована и не безопасна:
CREATE FUNCTION f2()RETURNS CHAR(36) CHARACTER SET utf8BEGIN RETURN UUID();END;
Эта функция изменяет данные, таким образом, это, возможно, не безопасно:
CREATE FUNCTION f3(p_id INT)RETURNS INTBEGIN UPDATE t SET modtime = NOW() WHERE id = p_id; RETURN ROW_COUNT();END;
Оценка природы функции основана на "честности" создателя: MySQL не проверяет что объявленная
функция DETERMINISTIC
свободно от операторов, которые приводят к
недетерминированным результатам.
Хотя возможно создать детерминированную сохраненную функцию без определения DETERMINISTIC
, невозможно выполнить эту функцию, используя основанное на
операторе двоичное журналирование. Чтобы выполнить такую функцию, следует использовать основанный на
строке или смешали двоичное журналирование. Альтернативно, если Вы явно определяете DETERMINISTIC
в функциональном определении можно использовать любой вид
журналирования, включая основанное на операторе журналирование.
Ослабить предыдущие условия на функциональном создании (что Вы должны иметь SUPER
полномочие и что
функция должна быть объявлена детерминированная или не изменить данные), установите глобальную
переменную log_bin_trust_function_creators
системная переменная к 1. По
умолчанию у этой переменной есть значение 0, но можно изменить ее как это:
mysql> SET GLOBAL
log_bin_trust_function_creators = 1;
Можно также установить эту переменную при использовании --log-bin-trust-function-creators=1
опция, запуская сервер.
Если двоичное журналирование не включается, log_bin_trust_function_creators
не применяется. SUPER
не требуется для функционального создания если, как описано
ранее, DEFINER
значение в функциональном определении требует этого.
Для получения информации о встроенных функциях, которые могут быть опасными для репликации (и таким образом вызвать сохраненные функции, которые используют их, чтобы быть опасными также), см. Раздел 16.4.1, "Функции репликации и Проблемы".
Триггеры подобны сохраненным функциям, таким образом, предыдущие комментарии относительно функций также
применяются к триггерам со следующим исключением: CREATE TRIGGER
не имеет дополнительного DETERMINISTIC
характеристика, таким образом, триггеры, как предполагается, всегда
детерминированы. Однако, это предположение могло бы в некоторых случаях быть недопустимым. Например, UUID()
функция
недетерминирована (и не тиражируется). Следует быть осторожными относительно использования таких функций в
триггерах.
Триггеры могут обновить таблицы, таким образом, сообщения об ошибках, подобные тем для сохраненных функций,
происходят с CREATE TRIGGER
если у Вас нет необходимых полномочий. На ведомой стороне
ведомое устройство использует триггер DEFINER
атрибут, чтобы определить, какой
пользователь, как полагают, является создателем триггера.
Остальная часть этого раздела обеспечивает дополнительную деталь о реализации журналирования и ее импликациях.
Вы не должны считать это, если Вам не интересно в фоновом режиме на объяснении для текущих связанных с
журналированием условий на сохраненном стандартном использовании. Это обсуждение применяется только для
основанного на операторе журналирования, а не для основанного на строке журналирования, за исключением первого
элемента: CREATE
и DROP
операторы регистрируются как
операторы независимо от режима журналирования.
Записи сервера CREATE
EVENT
, CREATE
PROCEDURE
, CREATE
FUNCTION
, ALTER EVENT
,
ALTER PROCEDURE
, ALTER FUNCTION
, DROP EVENT
, DROP PROCEDURE
, и DROP FUNCTION
операторы к двоичному журналу.
Сохраненный вызов функции регистрируется как a SELECT
оператор, если бы функция изменяет данные и происходит в пределах
оператора, который не был бы иначе зарегистрирован. Это предотвращает нерепликацию изменений данных,
которые следуют из использования сохраненных функций в незарегистрированных операторах. Например, SELECT
операторы не пишутся двоичному журналу, но a SELECT
мог бы вызвать сохраненную функцию, которая производит изменения. Обработать это, a SELECT
оператор
пишется двоичному журналу, когда заданная функция производит изменение. Предположите, что следующие
операторы выполняются на ведущем устройстве: func_name
()
CREATE FUNCTION f1(a INT) RETURNS INTBEGIN IF (a < 3) THEN INSERT INTO t2 VALUES (a); END IF; RETURN 0;END;CREATE TABLE t1 (a INT);INSERT INTO t1 VALUES (1),(2),(3);SELECT f1(a) FROM t1;
Когда SELECT
оператор выполняется, функция f1()
вызывается три раза. Два из тех вызовов вставляют строку, и MySQL
регистрирует a SELECT
оператор для каждого из них. Таким образом, MySQL пишет
следующие операторы в двоичный журнал:
SELECT f1(1);SELECT f1(2);
Сервер также регистрирует a SELECT
оператор для сохраненного вызова функции, когда функция вызывает хранимую процедуру, которая
вызывает ошибку. В этом случае сервер пишет SELECT
оператор к журналу наряду с ожидаемым кодом ошибки. На ведомом устройстве, если та же самая ошибка
происходит, который является ожидаемым результатом и репликацией, продолжается. Иначе, остановки
репликации.
У журналирования сохраненных вызовов функции, а не операторов, выполняемых функцией, есть импликация безопасности для репликации, которая является результатом двух факторов:
Для функции возможно следовать за различными путями выполнения на основных и ведомых серверах.
Операторы, выполняемые на ведомом устройстве, обрабатываются ведомым потоком SQL, у которого есть полные полномочия.
Импликация - это, хотя пользователь должен иметь CREATE ROUTINE
полномочие создать функцию, пользователь может
записать функцию, содержащую опасный оператор, который выполнится только на ведомом устройстве, где
это обрабатывается потоком, у которого есть полные полномочия. Например, если у основных и ведомых
серверов есть Значения идентификаторов сервера 1 и 2, соответственно, пользователь на главном
сервере мог создать и вызвать опасную функцию unsafe_func()
следующим
образом:
mysql>delimiter //
mysql>CREATE FUNCTION unsafe_func () RETURNS INT
->BEGIN
->IF @@server_id=2 THEN
->dangerous_statement
; END IF;RETURN 1;
->END;
->//
mysql>delimiter ;
mysql>INSERT INTO t VALUES(unsafe_func());
CREATE FUNCTION
и INSERT
операторы пишутся двоичному журналу, таким образом, ведомое
устройство выполнит их. Поскольку у ведомого потока SQL есть полные полномочия, он выполнит опасный
оператор. Таким образом вызов функции имеет различные эффекты на ведущее устройство и ведомое
устройство и не безопасен от репликации.
Чтобы принять меры против этой опасности для серверов, которым включали двоичному журналированию,
сохраненные функциональные создатели должны иметь SUPER
полномочие, в дополнение к обычному CREATE ROUTINE
полномочие, которое требуется. Точно так же
использовать ALTER
FUNCTION
, Вы должны иметь SUPER
полномочие в дополнение к ALTER ROUTINE
полномочие. Без SUPER
полномочие, ошибка произойдет:
ERROR 1419 (HY000): You do not have the SUPER privilege andbinary logging is enabled (you *might* want to use the less safelog_bin_trust_function_creators variable)
Если Вы не хотите требовать, чтобы функциональные создатели имели SUPER
полномочие (например, если все пользователи с CREATE ROUTINE
полномочие на Вашей системе является опытными
разработчиками приложений), установите глобальную переменную log_bin_trust_function_creators
системная переменная к 1. Можно
также установить эту переменную при использовании --log-bin-trust-function-creators=1
опция, запуская сервер. Если
двоичное журналирование не включается, log_bin_trust_function_creators
не применяется. SUPER
не требуется для функционального создания если, как описано
ранее, DEFINER
значение в функциональном определении требует этого.
Если функция, которая выполняет обновления, недетерминирована, это не повторимо. Это может иметь два нежелательных эффекта:
Это сделает ведомое устройство отличающимся от ведущего устройства.
Восстановленные данные будут отличаться от исходных данных.
Чтобы иметь дело с этими проблемами, MySQL осуществляет следующее требование: На главном сервере, создании и изменении функции отказывается, если Вы не объявляете, что функция детерминирована или не изменяет данные. Два набора функциональных характеристик применяются здесь:
DETERMINISTIC
и NOT
DETERMINISTIC
характеристики указывают, приводит ли функция всегда к тому же самому
результату для данных вводов. Значение по умолчанию NOT
DETERMINISTIC
если никакая характеристика не дается. Чтобы объявить, что функция
детерминирована, следует определить DETERMINISTIC
явно.
CONTAINS SQL
, NO
SQL
, READS SQL DATA
, и MODIFIES
SQL DATA
характеристики предоставляют информацию о ли функциональные чтения или
данные записей. Также NO SQL
или READS
SQL DATA
указывает, что функция не изменяет данные, но следует определить один из
них явно, потому что значение по умолчанию CONTAINS SQL
если
никакая характеристика не дается.
По умолчанию, для a CREATE
FUNCTION
оператор, который будет принят, по крайней мере один из DETERMINISTIC
,
NO SQL
, или READS SQL DATA
должен быть
определен явно. Иначе ошибка происходит:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL,or READS SQL DATA in its declaration and binary logging is enabled(you *might* want to use the less safe log_bin_trust_function_creatorsvariable)
Если Вы устанавливаете log_bin_trust_function_creators
к 1, требование, чтобы функции быть
детерминированными или не изменить данные были отброшены.
Вызовы хранимой процедуры регистрируются на уровне оператора, а не на CALL
уровень. Таким образом, сервер не регистрирует CALL
оператор, это регистрирует те операторы в пределах процедуры,
которые фактически выполняются. В результате те же самые изменения, которые происходят на ведущем
устройстве, будут наблюдаться относительно ведомых серверов. Это предотвращает проблемы, которые могли
следовать из процедуры, имеющей различные пути выполнения на различных машинах.
Вообще, операторы, выполняемые в пределах хранимой процедуры, пишутся двоичному журналу, используя те же самые правила, которые применялись бы, были операторы, которые будут выполняться автономным способом. Некоторая специальная забота проявляется, регистрируя операторы процедуры, потому что выполнение оператора в пределах процедур является не совсем тем же самым как в контексте непроцедуры:
Оператор, который будет зарегистрирован, мог бы содержать ссылки на локальные переменные процедуры. Эти переменные не существуют за пределами контекста хранимой процедуры, таким образом, оператор, который обращается к такой переменной, не может быть зарегистрирован буквально. Вместо этого каждая ссылка на локальную переменную заменяется этой конструкцией для того, чтобы зарегистрировать цели:
NAME_CONST(var_name
,var_value
)
var_name
имя локальной переменной, и var_value
постоянное указание на значение,
которое имеет переменная в то время, когда оператор регистрируется. NAME_CONST()
имеет значение var_value
, и "имя" var_name
.
Таким образом, если Вы вызываете эту функцию непосредственно, Вы получаете результат как
это:
mysql> SELECT
NAME_CONST('myname', 14);
+--------+| myname |+--------+| 14 |+--------+
NAME_CONST()
позволяет зарегистрированному автономному оператору выполняться на ведомом устройстве с
тем же самым эффектом как исходный оператор, который выполнялся на ведущем устройстве в
пределах хранимой процедуры.
Использование NAME_CONST()
может привести к проблеме для CREATE TABLE ...
SELECT
операторы, когда исходные выражения столбца обращаются к локальным
переменным. Преобразование этих ссылок на NAME_CONST()
выражения могут привести к именам
столбцов, которые отличаются на основных и ведомых серверах, или именах, которые
являются слишком длинными, чтобы быть юридическими идентификаторами столбца. Обходное
решение должно предоставить псевдонимы для столбцов, которые обращаются к локальным
переменным. Рассмотрите этот оператор когда myvar
имеет
значение 1:
CREATE TABLE t1 SELECT myvar;
Это будет переписано следующим образом:
CREATE TABLE t1 SELECT NAME_CONST(myvar, 1);
Чтобы гарантировать, что у основных и ведомых таблиц есть те же самые имена столбцов, запишите оператор как это:
CREATE TABLE t1 SELECT myvar AS myvar;
Переписанный оператор становится:
CREATE TABLE t1 SELECT NAME_CONST(myvar, 1) AS myvar;
Оператор, который будет зарегистрирован, мог бы содержать ссылки на
определяемые пользователем переменные. Чтобы обработать это, MySQL пишет a SET
оператор к двоичному журналу, чтобы удостовериться,
что переменная существует на ведомом устройстве с тем же самым значением как на ведущем
устройстве. Например, если оператор обращается к переменной @my_var
, тому оператору будет предшествовать в двоичном
журнале следующий оператор, где value
значение
@my_var
на ведущем устройстве:
SET @my_var = value
;
Вызовы процедуры могут произойти в пределах фиксировавшей или назад
прокрученной транзакции. Транзакционный контекст учитывается так, чтобы транзакционные
аспекты выполнения процедуры были тиражированы правильно. Таким образом, сервер регистрирует
те операторы в пределах процедуры, которые фактически выполняют и изменяют данные, и также
регистрирует BEGIN
, COMMIT
, и ROLLBACK
операторы по мере необходимости. Например, если
процедура обновляет только транзакционные таблицы и выполняется в пределах транзакции,
которая откатывается, те обновления не регистрируются. Если процедура происходит в пределах
фиксировавшей транзакции, BEGIN
и COMMIT
операторы регистрируются с обновлениями. Для
процедуры, которая выполняется в пределах назад прокрученной транзакции, ее операторы
регистрируются, используя те же самые правила, которые применялись бы, если бы операторы
выполнялись автономным способом:
Обновления к транзакционным таблицам не регистрируются.
Обновления к нетранзакционным таблицам регистрируются, потому что откат не отменяет их.
Обновления к соединению транзакционных и нетранзакционных
таблиц регистрируются окруженные BEGIN
и ROLLBACK
так, чтобы ведомые устройства
произвели те же самые изменения и откаты как на ведущем устройстве.
Вызов хранимой процедуры не пишется
двоичному журналу на уровне оператора, если процедура вызывается изнутри сохраненной функции. В этом
случае единственной зарегистрированной вещью является оператор, который вызывает функцию (если это
происходит в пределах оператора, который регистрируется), или a DO
оператор (если это происходит в пределах оператора, который не
регистрируется). Поэтому забота должна быть осуществлена в использовании сохраненных функций, которые
вызывают процедуру, даже если процедура иначе безопасна сам по себе.