Предупреждающий код Mysql 1592 Небезопасный оператор, записанный в двоичный журнал, используя формат оператора

Примечание (код 1592): Небезопасный оператор, записанный в двоичный журнал, используя формат оператора с BINLOG_FORMAT = ЗАЯВЛЕНИЕ. Записи, записываемые в таблицу с столбцом автоинкремент после выбора из другой таблицы, являются небезопасными, потому что порядок, в котором извлекаются строки, определяет, какие (если есть) строки будут записаны. Этот порядок не может быть предсказан и может отличаться на главном и подчиненном.

Я не понимаю вышеупомянутое сообщение об ошибке. Ниже приведены операторы/таблицы.

mysql> show create table phppos_app_config;
+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table             | Create Table                                                                                                                                                                                                                  |
+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_app_config | CREATE TABLE `phppos_app_config` (
  `key` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `value` text COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> \W
Show warnings enabled.
mysql> CREATE TABLE IF NOT EXISTS `phppos_locations` (
    ->   `location_id` int(11) NOT NULL AUTO_INCREMENT,
    ->   `name` text COLLATE utf8_unicode_ci,
    ->   `address` text COLLATE utf8_unicode_ci,
    ->   `phone` text COLLATE utf8_unicode_ci,
    ->   `fax` text COLLATE utf8_unicode_ci,
    ->   `email` text COLLATE utf8_unicode_ci,
    ->   `receive_stock_alert` text COLLATE utf8_unicode_ci,
    ->   `stock_alert_email` text COLLATE utf8_unicode_ci,
    ->   `return_policy` text COLLATE utf8_unicode_ci,
    ->   `timezone` text COLLATE utf8_unicode_ci,
    ->   `mailchimp_api_key` text COLLATE utf8_unicode_ci,
    ->   `enable_credit_card_processing` text COLLATE utf8_unicode_ci,
    ->   `merchant_id` text COLLATE utf8_unicode_ci,
    ->   `merchant_password` text COLLATE utf8_unicode_ci,
    ->   `default_tax_1_rate` text COLLATE utf8_unicode_ci,
    ->   `default_tax_1_name` text COLLATE utf8_unicode_ci,
    ->   `default_tax_2_rate` text COLLATE utf8_unicode_ci,
    ->   `default_tax_2_name` text COLLATE utf8_unicode_ci,
    ->   `default_tax_2_cumulative` text COLLATE utf8_unicode_ci,
    ->   `deleted` int(1) DEFAULT '0',
    ->   PRIMARY KEY (`location_id`),
    ->   KEY `deleted` (`deleted`)
    -> ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
Query OK, 0 rows affected (0.02 sec)

mysql> -- -------------------------------------------------
mysql> -- Migrate app config to location ---
mysql> -- -------------------------------------------------
mysql> 
mysql> INSERT INTO `phppos_locations` (`location_id`, `name`, `address`, `phone`, `fax`, `email`,
    -> `receive_stock_alert`, `stock_alert_email`, `return_policy`, `timezone`, `mailchimp_api_key`,
    ->  `enable_credit_card_processing`, `merchant_id`, `merchant_password`, `default_tax_1_rate`,
    -> `default_tax_1_name`,`default_tax_2_rate`, `default_tax_2_name`, `default_tax_2_cumulative`) VALUES(
    -> 1,
    -> 'Default',
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'address'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'phone'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'fax'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'email'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'receive_stock_alert'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'stock_alert_email'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'return_policy'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'timezone'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'mailchimp_api_key'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'enable_credit_card_processing'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'merchant_id'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'merchant_password'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'default_tax_1_rate'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'default_tax_1_name'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'default_tax_2_rate'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'default_tax_2_name'),
    -> (SELECT `value` FROM phppos_app_config WHERE `key` = 'default_tax_2_cumulative')
    -> );
Query OK, 1 row affected, 1 warning (0.00 sec)

Note (Code 1592): Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave.

Ответ 1

Вы, по-видимому, знакомы с двумя форматами двоичного ведения журнала, основанными на операторах - которые регистрируют фактические запросы, которые изменяют данные на главном компьютере, так что они могут быть выполненных на подчиненном устройстве и на основе строк, - который регистрирует предыдущие и/или последующие изображения фактических данных строки, которые были изменены запросом, так что подчиненный может непосредственно применить эти изменения к своим данным... и смешанные -mode, где оптимизатор и механизм хранения определяют, какой формат является оптимальным форматом для запроса по запросу.

Говоря о "сохранности" выражения в MySQL Replication, мы имеем в виду, можно ли корректно реплицировать оператор и его эффекты, используя формат, основанный на операторах. Если это относится к утверждению, мы считаем утверждение безопасным; в противном случае мы называем это небезопасным.

В общем, утверждение безопасно, если оно детерминировано и небезопасно, если оно не является.

http://dev.mysql.com/doc/refman/5.6/en/replication-rbr-safe-unsafe.html >

Оператор, который вы выполняете, в принципе небезопасен, потому что вы используете INSERT ... SELECT в таблице с столбцом автоматического увеличения. Если запрос этой общей формы был использован в среде с STATEMENT, а SELECT не возвращал строки в том же порядке на главном и подчиненном, строки могли быть выбраны в другом порядке и, таким образом, с различными значениями автоматического увеличения.

На практике конкретный запрос, который вы выполняете, является детерминированным, потому что вы вставляете только одну строку, и вы явно указываете значение автоинкремента. Я подозреваю, что причина твоей путаницы. Тем не менее, похоже, вы все еще вызываете предупреждение, потому что вы делаете INSERT ... SELECT в таблицу с автоматическим приращением, и сервер, по-видимому, применяет обобщенное "небезопасное" определение к запросу в принципе, а не точности.

Переключение binlog_format на MIXED должно привести к тому, что предупреждение исчезнет, ​​так как сервер может переключать режимы по своему усмотрению... и вряд ли будет иметь отрицательные побочные эффекты. Если бы не тот факт, что STATEMENT всегда был значением по умолчанию (так как изначально это был единственный доступ к репликации), я подозреваю, что они давно бы сделали MIXED по умолчанию... на самом деле, если вы познакомьтесь с внутренними двоичными журналами, вы, вероятно, будете склонны делать то, что я делаю, и используем ROW только обо всем... он имеет тенденцию делать гораздо более полезный двоичный журнал для устранения неполадок и поддержки себя из потому что "старые" данные строки регистрируются на DELETE и UPDATE.