警告 不安全语句写入二进制日志 using 语句
Warning Unsafe statement written to the binary log using statement
我已经创建了一个基于触发器的日志系统。
每次插入或更新一行时,触发器都会在另一个 table 中存储一个新行。
触发器工作正常,但一段时间后我在日志中发现了这条消息:
[Warning] Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly. Statement: update `gl_item` set `is_shown` = '0', `updated_at` = '2016-03-21 16:56:28' where `list_id` = '1' and `is_shown` = '1'
我已经 red 了一些与这个问题相关的 post 我喜欢:
- MySQL Replication & Triggers
但是我不明白问题的本质。
这个警告是什么意思?
我不必使用触发器插入自动增量列?
为了避免此警告,创建日志系统的最佳方法是什么?
更新
SHOW CREATE TABLE
的输出,这是触发器将输入 THE 行的 table。
gl_item_log | CREATE TABLE `gl_item_log` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Item log unique id',
`item_id` bigint(20) unsigned DEFAULT NULL ,
`updated_by` bigint(20) unsigned DEFAULT NULL ,
`switch_shown` tinyint(4) DEFAULT NULL ,
`switch_checked` tinyint(4) DEFAULT NULL ,
`logged_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`logged_at_microtime` decimal(6,6) unsigned NOT NULL ,
`logged_at_microtime_int` mediumint(8) unsigned NOT NULL DEFAULT '0' ,
PRIMARY KEY (`id`),
KEY `gl_item_log_updated_by_foreign` (`updated_by`),
KEY `gl_item_log_item_id_updated_by_switch_shown_switch_checked_index`
(`item_id`,`updated_by`,`switch_shown`,`switch_checked`),
CONSTRAINT `gl_item_log_item_id_foreign`
FOREIGN KEY (`item_id`) REFERENCES `gl_item` (`id`),
CONSTRAINT `gl_item_log_updated_by_foreign`
FOREIGN KEY (`updated_by`) REFERENCES `gl_general_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
删除带有自动递增字段的 id
列,以便日志条目没有唯一标识符是个好主意吗?
谢谢
What this warning mean?
According to the MySQL documentation:
A statement invoking a trigger (or function) that causes an update to an AUTO_INCREMENT column is not replicated correctly using statement-based replication. MySQL 5.7 marks such statements as unsafe. (Bug #45677)
使用 statement-based replication,确切的 SQL 在您的主数据库上是 运行,在您的从属数据库上也是 运行。当您的触发器被触发时,如果它存在于您的每个数据库中,则它在每个数据库上都是 运行 并插入到您的日志中。要让您的数据库保持同步,这可能是一个棘手的情况。
I don't have to insert into auto increment column with triggers?
正确。永远不需要将您自己的值插入到自动增量列中。
Which is the best way to create a log system in order to avoid this warning?
首先,要么在每个数据库上保留触发器并关闭日志 table 的复制,要么只在主数据库上使用触发器并让复制将日志 table 插入复制到其他数据库。
要解决此特定警告,请将您的日志 table 配置为没有自动递增列。然后您的触发器可以插入其中,它不应导致任何复制警告。
另一种选择是切换到基于行的复制。然后触发器只会在主服务器上自动触发,自动增量值将始终毫无问题地复制。
我已经创建了一个基于触发器的日志系统。
每次插入或更新一行时,触发器都会在另一个 table 中存储一个新行。
触发器工作正常,但一段时间后我在日志中发现了这条消息:
[Warning] Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly. Statement: update `gl_item` set `is_shown` = '0', `updated_at` = '2016-03-21 16:56:28' where `list_id` = '1' and `is_shown` = '1'
我已经 red 了一些与这个问题相关的 post 我喜欢:
- MySQL Replication & Triggers
但是我不明白问题的本质。
这个警告是什么意思?
我不必使用触发器插入自动增量列?
为了避免此警告,创建日志系统的最佳方法是什么?
更新
SHOW CREATE TABLE
的输出,这是触发器将输入 THE 行的 table。
gl_item_log | CREATE TABLE `gl_item_log` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Item log unique id',
`item_id` bigint(20) unsigned DEFAULT NULL ,
`updated_by` bigint(20) unsigned DEFAULT NULL ,
`switch_shown` tinyint(4) DEFAULT NULL ,
`switch_checked` tinyint(4) DEFAULT NULL ,
`logged_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`logged_at_microtime` decimal(6,6) unsigned NOT NULL ,
`logged_at_microtime_int` mediumint(8) unsigned NOT NULL DEFAULT '0' ,
PRIMARY KEY (`id`),
KEY `gl_item_log_updated_by_foreign` (`updated_by`),
KEY `gl_item_log_item_id_updated_by_switch_shown_switch_checked_index`
(`item_id`,`updated_by`,`switch_shown`,`switch_checked`),
CONSTRAINT `gl_item_log_item_id_foreign`
FOREIGN KEY (`item_id`) REFERENCES `gl_item` (`id`),
CONSTRAINT `gl_item_log_updated_by_foreign`
FOREIGN KEY (`updated_by`) REFERENCES `gl_general_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
删除带有自动递增字段的 id
列,以便日志条目没有唯一标识符是个好主意吗?
谢谢
What this warning mean?
According to the MySQL documentation:
A statement invoking a trigger (or function) that causes an update to an AUTO_INCREMENT column is not replicated correctly using statement-based replication. MySQL 5.7 marks such statements as unsafe. (Bug #45677)
使用 statement-based replication,确切的 SQL 在您的主数据库上是 运行,在您的从属数据库上也是 运行。当您的触发器被触发时,如果它存在于您的每个数据库中,则它在每个数据库上都是 运行 并插入到您的日志中。要让您的数据库保持同步,这可能是一个棘手的情况。
I don't have to insert into auto increment column with triggers?
正确。永远不需要将您自己的值插入到自动增量列中。
Which is the best way to create a log system in order to avoid this warning?
首先,要么在每个数据库上保留触发器并关闭日志 table 的复制,要么只在主数据库上使用触发器并让复制将日志 table 插入复制到其他数据库。
要解决此特定警告,请将您的日志 table 配置为没有自动递增列。然后您的触发器可以插入其中,它不应导致任何复制警告。
另一种选择是切换到基于行的复制。然后触发器只会在主服务器上自动触发,自动增量值将始终毫无问题地复制。