mysql崩溃,重复密钥查询更新

时间:2017-09-23 13:13:33

标签: mysql blob on-duplicate-key

最近,生产MySQL服务器在从5.5升级到5.7.19后偶尔崩溃。以下是错误日志中的堆栈跟踪以及与有问题的查询相关的表。我每次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的错误吗?我发现了一个相关问题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                    |
+-------------------+---------------------------+

3 个答案:

答案 0 :(得分:1)

看起来与https://bugs.mysql.com/bug.php?id=79243https://bugs.launchpad.net/percona-server/+bug/1667552相同我建议对上游错误发表评论,然后点击该错误并点击“影响我”。

答案 1 :(得分:0)

MySQL 5.7.19更新日志说明了这个错误:

  

如果ON DUPLICATE KEY UPDATE子句的VALUES部分引用INSERT列列表中的BLOB值,则在存储程序或预准备语句上下文中执行的INSERT语句可能会发生不正确的行为。 (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);

此语法表示将报告列设置为您尝试在第一行中插入的值。它只是简写,因此您不必为每列重复两次文字值。

错误描述似乎表明,如果您在存储过程或预准备语句中执行此操作,则会导致崩溃。我喜欢使用VALUES()技巧,因为它很方便,但我不能说我已经在5.7.19中的存储过程中用blob尝试过它。

鉴于错误的措辞&#34;如果ON DUPLICATE KEY UPDATE子句的VALUES部分引用了BLOB值...&#34;,我认为它可以解决问题,如果您可以显式重复整个blob值,而不是使用VALUES()简写。

否则,如果存在问题,请不要在存储过程中执行此操作。

答案 2 :(得分:0)

threads_connected~2500 +表示当客户端使用完系统后,没有正在处理注销/注销断开连接。

为了避免线程创建/终止流失,我会在my.ini / cnf中进行更改 thread_cache_size = 100        #8从8开始,建议在8.0中建议    支持在此实例中创建的5,000多个线程。

如需更详细的分析,请发布

RAM   on your server
SHOW GLOBAL STATUS;
SHOW GLOBAL VARIABLES;
SHOW ENGINE INNODB STATUS;

和一般记录的一分钟。