Bug #53592 crash replacing duplicates into table after fast alter table added unique key
Submitted: 12 May 2010 7:52 Modified: 14 Oct 2010 15:19
Reporter: Shane Bester (Platinum Quality Contributor) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S1 (Critical)
Version:plugin 1.0.7, 5.1.46, 5.5.x OS:Any
Assigned to: Jimmy Yang CPU Architecture:Any

[12 May 2010 7:52] Shane Bester
Description:
valgrind errors and/or crash when replacing duplicates into a table after fast alter table added a unique prefix index:

ha_innodb_plugin.dll!mach_read_from_2()[mach0data.ic:87]
ha_innodb_plugin.dll!rec_get_next_offs()[rem0rec.ic:337]
ha_innodb_plugin.dll!row_search_for_mysql()[row0sel.c:3797]
ha_innodb_plugin.dll!ha_innodb::index_read()[ha_innodb.cc:5397]
ha_innodb_plugin.dll!handler::index_read_map()[handler.h:1402]
mysqld-debug.exe!handler::index_read_idx_map()[handler.cc:4312]
mysqld-debug.exe!write_record()[sql_insert.cc:1450]
mysqld-debug.exe!mysql_insert()[sql_insert.cc:835]
mysqld-debug.exe!mysql_execute_command()[sql_parse.cc:3183]
mysqld-debug.exe!mysql_parse()[sql_parse.cc:5975]
mysqld-debug.exe!dispatch_command()[sql_parse.cc:1235]
mysqld-debug.exe!do_command()[sql_parse.cc:874]
mysqld-debug.exe!handle_one_connection()[sql_connect.cc:1127]
mysqld-debug.exe!pthread_start()[my_winthread.c:85]
mysqld-debug.exe!_callthreadstart()[thread.c:295]
mysqld-debug.exe!_threadstart()[thread.c:277]

How to repeat:
#start server with innodb plugin enabled

set sql_mode='';
set old_alter_table=0;
drop table if exists `t1`;
create table `t1`(`a` int)
engine=innodb row_format=compact;
alter table `t1` add column `b` text charset utf8;
alter table `t1` add column `c` blob not null ;
create index `idx1` on `t1`(`b`(81)) ;
create unique index `idx2` on `t1`(`c`(1)) ;
replace into `t1` values (),();
[12 May 2010 7:55] MySQL Verification Team
valgrind output from plugin 1.0.7/5.1.46

Attachment: bug53592_valgrind_1.0.7_plugin_output.txt (text/plain), 11.92 KiB.

[12 May 2010 9:22] Valeriy Kravchuk
Yet another indication of this bug:

C:\Program Files\MySQL\MySQL Server 5.1\bin>mysql -uroot  -P3312 test
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.3-m3-community MySQL Community Server (GPL)

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL v2 license

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> set sql_mode='';
Query OK, 0 rows affected (0.02 sec)

mysql> set old_alter_table=0;
Query OK, 0 rows affected (0.00 sec)

mysql> drop table if exists `t1`;
Query OK, 0 rows affected, 1 warning (0.05 sec)

mysql> create table `t1`(`a` int)
    -> engine=innodb row_format=compact;
Query OK, 0 rows affected (0.33 sec)

mysql> alter table `t1` add column `b` text charset utf8;
Query OK, 0 rows affected (0.50 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table `t1` add column `c` blob not null ;
Query OK, 0 rows affected (0.33 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> create index `idx1` on `t1`(`b`(81)) ;
Query OK, 0 rows affected (0.42 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> create unique index `idx2` on `t1`(`c`(1)) ;
ERROR 5 (HY000): Out of memory (Needed 1684892816 bytes)

This is obviously a result of some garbage reading...
[17 May 2010 7:20] Marko Mäkelä
This seems to be caused by a memory overwrite:

#0  key_copy (to_key=0xa7ae91b0 "\230\356\r\t\017", from_record=0x90df018 "\377", key_info=0x90dcef4, key_length=246) at key.cc:116
#1  0x08317e1e in write_record (thd=0x90b4648, table=0x90e5d68, info=0xa7ae933c) at sql_insert.cc:1447
#2  0x083166ba in mysql_insert (thd=0x90b4648, table_list=0x90dde50, fields=..., values_list=..., update_fields=..., update_values=..., duplic=DUP_REPLACE, ignore=false) at sql_insert.cc:835

key_copy() is invoked with key_length=0 for the empty tuple (), and it apparently gets the wrong key_length=246 from key_info->key_length. I have to check where the key_info is coming from.
[17 May 2010 8:06] Marko Mäkelä
I analyzed this with the following test case:

# Bug #53592 crash replacing duplicates into table after CREATE UNIQUE KEY

-- source include/have_innodb_plugin.inc

set old_alter_table=1;
create table bug53592(a int) engine=innodb row_format=compact;
alter table bug53592 add column b text charset utf8;
alter table bug53592 add column c blob not null;
create index bug53592_b on bug53592(b(81));
create unique index bug53592_c on bug53592(c(1));
replace into bug53592 values (),();
drop table bug53592;

set old_alter_table=0;
create table bug53592(a int) engine=innodb row_format=compact;
alter table bug53592 add column b text charset utf8;
alter table bug53592 add column c blob not null;
create index bug53592_b on bug53592(b(81));
create unique index bug53592_c on bug53592(c(1));
replace into bug53592 values (),();
drop table bug53592;

On both runs of REPLACE INTO, the table->key_info looks fine in write_record(). On each run, the duplicate is detected on c(1). On the first run, key_nr==0 as it should be. On the second run, row_get_mysql_key_number_for_index() returns key_nr==1, which is wrong. It should use the index translation table.

I will assign this bug to Jimmy Yang, who implemented the index translation table.

I think that the index translation table must be used in the built-in InnoDB in MySQL 5.1 as well. Otherwise, users who have created indexes with the plugin and downgraded to the built-in InnoDB may get nasty surprises.
[31 May 2010 8:28] Bugs System
Pushed into 5.1.48 (revid:vasil.dimov@oracle.com-20100531082307-9x08gg1g7zybx2jy) (version source revid:vasil.dimov@oracle.com-20100531082307-9x08gg1g7zybx2jy) (merge vers: 5.1.48) (pib:16)
[17 Jun 2010 6:13] Bugs System
Pushed into 5.5.5-m3 (revid:alexey.kopytov@sun.com-20100615145247-8bj0vmuqlotbqsn9) (version source revid:sergey.glukhov@sun.com-20100531094123-fzraiul1muim1lxa) (merge vers: 5.5.5-m3) (pib:16)
[17 Jun 2010 6:16] Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100615150216-cubqoyn1fj9b6a2p) (version source revid:alik@sun.com-20100601061436-dq8e2nfqfa01r06b) (pib:16)
[18 Jun 2010 0:11] Paul DuBois
Noted in 5.1.48, 5.5.5 changelogs.

InnoDB crashed when replacing duplicates in a table after a fast
ALTER TABLE added a unique index.
[14 Oct 2010 8:34] Bugs System
Pushed into mysql-5.1-telco-7.0 5.1.51-ndb-7.0.20 (revid:martin.skold@mysql.com-20101014082627-jrmy9xbfbtrebw3c) (version source revid:vasil.dimov@oracle.com-20100531152341-x2d4hma644icamh1) (merge vers: 5.5.5-m3) (pib:21)
[14 Oct 2010 8:50] Bugs System
Pushed into mysql-5.1-telco-6.3 5.1.51-ndb-6.3.39 (revid:martin.skold@mysql.com-20101014083757-5qo48b86d69zjvzj) (version source revid:vasil.dimov@oracle.com-20100531152341-x2d4hma644icamh1) (merge vers: 5.5.5-m3) (pib:21)
[14 Oct 2010 9:04] Bugs System
Pushed into mysql-5.1-telco-6.2 5.1.51-ndb-6.2.19 (revid:martin.skold@mysql.com-20101014084420-y54ecj85j5we27oa) (version source revid:vasil.dimov@oracle.com-20100531152341-x2d4hma644icamh1) (merge vers: 5.5.5-m3) (pib:21)
[14 Oct 2010 15:19] Jon Stephens
Already documented in the 5.1.48 changelog; no new changelog entries required. setting back to Closed state.