Небезопасные операторы для репликации на основе операторов
Безопасный оператор, как правило, детерминирован; другими словами, оператор всегда будет давать один и тот же результат. Например, оператор INSERT, генерирующий случайное число, скорее всего, даст разные результаты на первичном и на реплицируемом сервере, и поэтому не может быть безопасно реплицирован.
При выполнении небезопасного оператора текущий формат протоколирования двоичных данных определяет, как сервер отреагирует.
- Если формат протоколирования двоичных данных является операторным (по умолчанию до MariaDB 10.2.3), небезопасные операторы генерируют предупреждение и регистрируются в обычном режиме.
- Если формат протоколирования двоичных данных является смешанным (по умолчанию начиная с MariaDB 10.2.4), небезопасные операторы регистрируются с помощью формата на основе строк, а безопасные операторы — с помощью операторного формата.
- Если формат протоколирования двоичных данных является на основе строк, все операторы регистрируются в обычном режиме, и различие между безопасными и небезопасными операторами не делается.
MariaDB пытается обнаружить небезопасные операторы. При выполнении небезопасного оператора генерируется предупреждение, подобное следующему:
Note (Code 1592): Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
MariaDB также выдает это предупреждение для некоторых категорий безопасных операторов.
Небезопасные операторы
Следующие операторы считаются небезопасными:
- INSERT ... ON DUPLICATE KEY UPDATE операторы для таблиц с несколькими первичными или уникальными ключами, поскольку порядок проверки ключей и, следовательно, строк, которые будут обновлены, не является детерминированным. До MariaDB 5.5.24 эти операторы не считались небезопасными. В MariaDB 10.0 это предупреждение было удалено, так как мы всегда проверяем ключи в том же порядке на первичном и реплицируемом серверах, если первичный и реплицируемый сервера используют один и тот же движок хранения.
- INSERT-DELAYED. Эти операторы вставляются в неопределенном порядке.
- INSERT в таблицы с составным первичным ключом, содержащим столбец AUTO_INCREMENT, который не является первым столбцом составного ключа.
- Когда таблица имеет столбец AUTO_INCREMENT и триггер trigger или хранимая процедура stored procedure выполняет оператор UPDATE для этой таблицы. До MariaDB 5.5 все обновления для таблиц со столбцом AUTO_INCREMENT считались небезопасными, так как порядок обновления строк мог отличаться на разных серверах.
-
UPDATE операторы, использующие LIMIT, так как порядок возвращаемых строк не указан. Это относится даже к операторам, использующим предложение ORDER BY, которое детерминировано (известная ошибка). Однако начиная с MariaDB 10.0.11,
LIMIT 0является исключением из этого правила (см. MDEV-6170), и эти операторы безопасны для репликации. - При использовании пользовательской функции.
- Операторы, использующие следующие функции, которые могут возвращать разные результаты на реплицируемом сервере:
- Операторы, которые ссылаются на таблицы журналов, поскольку они могут отличаться на разных серверах.
- Операторы, которые ссылаются на таблицы самозаписи. Операторы, выполняемые после чтения или записи в таблицу самозаписи в рамках транзакции, также считаются небезопасными.
- Операторы, которые ссылаются на переменные сервера (есть несколько исключений).
- LOAD DATA INFILE операторы (начиная с MariaDB 5.5).
- Нетранзакционные чтение или запись, которые выполняются после транзакционного чтения в рамках транзакции.
- Если для оператора используется протоколирование на основе строк, и сессия, выполняющая оператор, имеет временные таблицы, протоколирование на основе строк используется для оставшихся операторов до момента удаления временной таблицы. Это связано с тем, что временные таблицы не могут использовать протоколирование на основе строк, поэтому если оно используется из-за одного из вышеуказанных условий, все последующие операторы, использующие эту таблицу, являются небезопасными. Сервер обрабатывает эту ситуацию, рассматривая все операторы в сессии как небезопасные для операторного протоколирования, пока временная таблица не будет удалена.
Безопасные операторы
Следующие операторы не являются детерминированными, но считаются безопасными для протоколирования двоичных данных и репликации:
- CONNECTION_ID()
- CURDATE()
- CURRENT_DATE()
- CURRENT_TIME()
- CURRENT_TIMESTAMP()
- CURTIME()
- LAST_INSERT_ID()
- LOCALTIME()
- LOCALTIMESTAMP()
- NOW()
- UNIX_TIMESTAMP()
- UTC_DATE()
- UTC_TIME()
- UTC_TIMESTAMP()
Уровни изоляции
Даже при использовании безопасных операторов не все уровни изоляции транзакций безопасны при использовании операторного или смешанного протоколирования двоичных данных. Уровни изоляции REPEATABLE READ и SERIALIZABLE могут использоваться только с форматом на основе строк.
Это ограничение не применяется, если используются только не транзакционные движки хранения.
См. также
© 2023 MariaDB
Licensed under the Creative Commons Attribution 3.0 Unported License and the GNU Free Documentation License.
https://mariadb.com/kb/en/unsafe-statements-for-statement-based-replication/