mysql 更新重复键查询时崩溃
mysql crash with update on duplicate key query
最近,生产 MySQL 服务器在从 5.5 升级到 5.7.19 后偶尔会崩溃。以下是错误日志中的堆栈跟踪和与有问题的查询相关的 table。我打开了通用日志,每次 MySQL 都崩溃了。最近几个日志条目中有一个非常大的 insert on duplicate key
查询。
0xf4bd75 my_print_stacktrace + 53
0x7d0144 handle_fatal_signal + 1188
0x34d8a0f710 _end + -693094128
0x800b23 Field_blob::copy_blob_value(st_mem_root*) + 51
0xe9af6e mysql_prepare_blob_values(THD*, List<Item>&, st_mem_root*) + 686
0xe9b575 write_record(THD*, TABLE*, COPY_INFO*, COPY_INFO*) + 565
0xe9c952 Sql_cmd_insert::mysql_insert(THD*, TABLE_LIST*) + 2146
0xe9d16e Sql_cmd_insert::execute(THD*) + 222
0xd10279 mysql_execute_command(THD*, bool) + 4025
0xd1481d mysql_parse(THD*, Parser_state*) + 1005
0xd160ac dispatch_command(THD*, COM_DATA const*, enum_server_command) + 6188
0xd16a74 do_command(THD*) + 404
0xdea70c handle_connection + 668
0xf69d64 pfs_spawn_thread + 372
0x34d8a079d1 _end + -693126191
0x311e4e8b6d _end + 475909485
CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`col2` varchar(128) DEFAULT NULL,
`col3` int(11) DEFAULT NULL ,
`col4` int(11) DEFAULT NULL ,
`col5` int(11) DEFAULT NULL ,
`col6` int(11) DEFAULT NULL ,
`col7` varchar(128) DEFAULT NULL ,
`col8` varchar(1024) DEFAULT NULL ,
`report` longtext ,
`create_date` datetime DEFAULT NULL ,
`start_date` datetime DEFAULT NULL ,
`finish_date` datetime DEFAULT NULL ,
`state` varchar(128) DEFAULT NULL ,
`col9` text ,
`col10` int(11) DEFAULT NULL ,
`col11` int(11) DEFAULT NULL ,
`col12` text ,
`count_post` int(11) DEFAULT NULL ,
`count_reply` int(11) DEFAULT NULL ,
`count_link` int(11) DEFAULT NULL ,
`remark` text ,
PRIMARY KEY (`id`),
UNIQUE KEY `col2` (`col2`),
KEY `col4` (`col4`),
KEY `col5` (`col5`),
KEY `col6` (`col6`),
KEY `col7` (`col7`),
KEY `create_date` (`create_date`),
KEY `finish_date` (`finish_date`)
) ENGINE=InnoDB AUTO_INCREMENT=405597973 DEFAULT CHARSET=utf8'
这是5.7.19的bug吗?我发现了一个相关问题 Crash on UPDATE ON DUPLICATE KEY 但我无法重复。我该如何避免或如何修复它?
正如 Wilson Hauck 所指出的,以下是与 threads_%
相关的内容
mysql> SHOW GLOBAL STATUS LIKE 'threads_%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 1 |
| Threads_connected | 2530 |
| Threads_created | 5920 |
| Threads_running | 2 |
+-------------------+-------+
mysql> SHOW GLOBAL VARIABLES LIKE 'thread_%';
+-------------------+---------------------------+
| Variable_name | Value |
+-------------------+---------------------------+
| thread_cache_size | 8 |
| thread_handling | one-thread-per-connection |
| thread_stack | 262144 |
+-------------------+---------------------------+
MySQL 5.7.19 更新日志在已修复的错误中说明了这一点:
Incorrect behavior could occur for INSERT statements executed in stored-program or prepared-statement context, if the VALUES part of an ON DUPLICATE KEY UPDATE clause referred to a BLOB value in the INSERT column list. (Bug #24538207, Bug #25361251, Bug #25530880, Bug #25684790)
显然他们没有在 5.7.19 中完全修复它。 :-(
但它向我建议了一个解决方法。
如果你有这样的陈述:
INSERT INTO t (id, report) VALUES (1234, 'report report report')
ON DUPLICATE KEY UPDATE report='report report report';
您可以重写它以避免在 UPDATE 子句中使用 blob 值:
INSERT INTO t (id, report) VALUES (1234, 'report report report')
ON DUPLICATE KEY UPDATE report=VALUES(report);
此语法意味着将报告列设置为您尝试在第一行中插入的相同值。它只是 shorthand,因此您不必为每一列重复文字值两次。
错误描述似乎是说如果您在存储过程或准备好的语句中执行此操作会导致崩溃。我喜欢使用 VALUES() 技巧,因为它很方便,但我不能说我已经在 5.7.19 的存储过程中用 blob 尝试过它。
鉴于错误的措辞 "if the VALUES part of an ON DUPLICATE KEY UPDATE clause referred to a BLOB value...",我认为如果您显式重复整个 blob 值而不是使用 VALUES()
shorthand,它可能会解决该问题。
否则不要在存储过程中执行此操作,如果这是问题所在。
threads_connected ~2500+ 表示没有 logout/logoff 客户端使用完系统后正在处理断开连接。
为了避免线程 creation/termination 流失,我会更改我的。ini/cnf
thread_cache_size = 100
# 对于 8.0 中建议的 CAP,从 8 开始
支持在此实例中创建的 5,000 多个线程。
更详细的分析请post
RAM on your server
SHOW GLOBAL STATUS;
SHOW GLOBAL VARIABLES;
SHOW ENGINE INNODB STATUS;
还有一分钟的一般日志。
看起来与 https://bugs.mysql.com/bug.php?id=79243 and https://bugs.launchpad.net/percona-server/+bug/1667552 相同 我建议对上游错误发表评论并关注该错误并单击 'Affects me'。
最近,生产 MySQL 服务器在从 5.5 升级到 5.7.19 后偶尔会崩溃。以下是错误日志中的堆栈跟踪和与有问题的查询相关的 table。我打开了通用日志,每次 MySQL 都崩溃了。最近几个日志条目中有一个非常大的 insert on duplicate key
查询。
0xf4bd75 my_print_stacktrace + 53
0x7d0144 handle_fatal_signal + 1188
0x34d8a0f710 _end + -693094128
0x800b23 Field_blob::copy_blob_value(st_mem_root*) + 51
0xe9af6e mysql_prepare_blob_values(THD*, List<Item>&, st_mem_root*) + 686
0xe9b575 write_record(THD*, TABLE*, COPY_INFO*, COPY_INFO*) + 565
0xe9c952 Sql_cmd_insert::mysql_insert(THD*, TABLE_LIST*) + 2146
0xe9d16e Sql_cmd_insert::execute(THD*) + 222
0xd10279 mysql_execute_command(THD*, bool) + 4025
0xd1481d mysql_parse(THD*, Parser_state*) + 1005
0xd160ac dispatch_command(THD*, COM_DATA const*, enum_server_command) + 6188
0xd16a74 do_command(THD*) + 404
0xdea70c handle_connection + 668
0xf69d64 pfs_spawn_thread + 372
0x34d8a079d1 _end + -693126191
0x311e4e8b6d _end + 475909485
CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`col2` varchar(128) DEFAULT NULL,
`col3` int(11) DEFAULT NULL ,
`col4` int(11) DEFAULT NULL ,
`col5` int(11) DEFAULT NULL ,
`col6` int(11) DEFAULT NULL ,
`col7` varchar(128) DEFAULT NULL ,
`col8` varchar(1024) DEFAULT NULL ,
`report` longtext ,
`create_date` datetime DEFAULT NULL ,
`start_date` datetime DEFAULT NULL ,
`finish_date` datetime DEFAULT NULL ,
`state` varchar(128) DEFAULT NULL ,
`col9` text ,
`col10` int(11) DEFAULT NULL ,
`col11` int(11) DEFAULT NULL ,
`col12` text ,
`count_post` int(11) DEFAULT NULL ,
`count_reply` int(11) DEFAULT NULL ,
`count_link` int(11) DEFAULT NULL ,
`remark` text ,
PRIMARY KEY (`id`),
UNIQUE KEY `col2` (`col2`),
KEY `col4` (`col4`),
KEY `col5` (`col5`),
KEY `col6` (`col6`),
KEY `col7` (`col7`),
KEY `create_date` (`create_date`),
KEY `finish_date` (`finish_date`)
) ENGINE=InnoDB AUTO_INCREMENT=405597973 DEFAULT CHARSET=utf8'
这是5.7.19的bug吗?我发现了一个相关问题 Crash on UPDATE ON DUPLICATE KEY 但我无法重复。我该如何避免或如何修复它?
正如 Wilson Hauck 所指出的,以下是与 threads_%
mysql> SHOW GLOBAL STATUS LIKE 'threads_%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 1 |
| Threads_connected | 2530 |
| Threads_created | 5920 |
| Threads_running | 2 |
+-------------------+-------+
mysql> SHOW GLOBAL VARIABLES LIKE 'thread_%';
+-------------------+---------------------------+
| Variable_name | Value |
+-------------------+---------------------------+
| thread_cache_size | 8 |
| thread_handling | one-thread-per-connection |
| thread_stack | 262144 |
+-------------------+---------------------------+
MySQL 5.7.19 更新日志在已修复的错误中说明了这一点:
Incorrect behavior could occur for INSERT statements executed in stored-program or prepared-statement context, if the VALUES part of an ON DUPLICATE KEY UPDATE clause referred to a BLOB value in the INSERT column list. (Bug #24538207, Bug #25361251, Bug #25530880, Bug #25684790)
显然他们没有在 5.7.19 中完全修复它。 :-(
但它向我建议了一个解决方法。
如果你有这样的陈述:
INSERT INTO t (id, report) VALUES (1234, 'report report report')
ON DUPLICATE KEY UPDATE report='report report report';
您可以重写它以避免在 UPDATE 子句中使用 blob 值:
INSERT INTO t (id, report) VALUES (1234, 'report report report')
ON DUPLICATE KEY UPDATE report=VALUES(report);
此语法意味着将报告列设置为您尝试在第一行中插入的相同值。它只是 shorthand,因此您不必为每一列重复文字值两次。
错误描述似乎是说如果您在存储过程或准备好的语句中执行此操作会导致崩溃。我喜欢使用 VALUES() 技巧,因为它很方便,但我不能说我已经在 5.7.19 的存储过程中用 blob 尝试过它。
鉴于错误的措辞 "if the VALUES part of an ON DUPLICATE KEY UPDATE clause referred to a BLOB value...",我认为如果您显式重复整个 blob 值而不是使用 VALUES()
shorthand,它可能会解决该问题。
否则不要在存储过程中执行此操作,如果这是问题所在。
threads_connected ~2500+ 表示没有 logout/logoff 客户端使用完系统后正在处理断开连接。
为了避免线程 creation/termination 流失,我会更改我的。ini/cnf
thread_cache_size = 100
# 对于 8.0 中建议的 CAP,从 8 开始
支持在此实例中创建的 5,000 多个线程。
更详细的分析请post
RAM on your server
SHOW GLOBAL STATUS;
SHOW GLOBAL VARIABLES;
SHOW ENGINE INNODB STATUS;
还有一分钟的一般日志。
看起来与 https://bugs.mysql.com/bug.php?id=79243 and https://bugs.launchpad.net/percona-server/+bug/1667552 相同 我建议对上游错误发表评论并关注该错误并单击 'Affects me'。