Bug #49730 During Fast Index creation mysql client is locked

Submitted: 16 Dec 2009 6:09 Modified: 26 Jan 2011 13:51
Reporter: Vadim TKACHENKO Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: Locking Severity:S2 (Serious)
Version:5.1.47 + plugin 1.0.8, 5.5.5, 5.6.99 OS:Any
Assigned to: Assigned Account CPU Architecture:Any
Tags: fast alter table

[16 Dec 2009 6:09] Vadim TKACHENKO
Description:
When InnoDB-plugin creates index on some time, mysql client
hangs on command
use DB;

where DB is database that contains the table where index is being created.

For example

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show processlist;
+----+------+-----------+----------+------------+------+-------------------+--------------------------------------+
| Id | User | Host      | db       | Command    | Time | State             | Info                                 |
+----+------+-----------+----------+------------+------+-------------------+--------------------------------------+
|  1 | root | localhost | wikistat | Query      |   54 | manage keys       | alter table pages3 add key (crchash) |
|  7 | root | localhost | wikistat | Field List |   25 | Waiting for table |     

process 1 - is process with creating index.
process 7 is process:

mysql> use wikistat;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

So as you see process 7 hang in Command Field List State "Waiting for table"

How to repeat:
Create index in one thread
and
execute
use DB 
in another

Suggested fix:
Do not block mysql client
[16 Dec 2009 8:22] Sveta Smirnova
Thank you for the report.

I can not repeat described behavior with dummy data. Please provide output of SHOW CREATE TABLE pages3
[16 Dec 2009 14:19] Vadim TKACHENKO
Sveta,

Schema is

CREATE TABLE `pages3` (
  `id` int(10) unsigned NOT NULL,
  `page` varchar(2000) NOT NULL,
  `crchash` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `crchash` (`crchash`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8

Parameters are:
innodb_buffer_pool_size=12G
innodb_log_file_size=256M
innodb_flush_log_at_trx_commit=2
innodb_flush_method=O_DIRECT

ignore-builtin-innodb
plugin-load=innodb=ha_innodb_plugin.so
plugin_dir=/data/vol1/engines/mysql-5.1.41/mysql-5.1.41-linux-x86_64-glibc23/lib/plugin
innodb_file_per_table=1
innodb_file_format=Barracuda
[18 Dec 2009 16:03] Sveta Smirnova
Thank you for the feedback.

I still can not repeat described behavior, although I can prove InnoDB Plugin locks LOCK_open while alters table and InnoDB does not.

Could you please attach gdb in locking time, then run `bt` and `bt full` commands and send us output, so we can see where it is locked?
[19 Dec 2009 6:05] Vadim TKACHENKO
Sveta,

Make sure you have big amount of data so ALTER TABLE ADD KEY runs long enough.

Here is bt for relevant threads

Thread 4 (Thread 0x49478940 (LWP 11198)):
#0  0x00000000008e106d in adler32 (adler=196091, 
    buf=0x2aac9b1d0d62 "%D1%82%D1%80%D0%BE%D0%BD%D0%BD%D0%B0%D1%8F_%D0%BF%D1%80%D0%BE%D0%BC%D1%8B%D1%88%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D1%8C/[???,\2011\004:?M%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%AD"..., len=10798) at adler32.c:101
#1  0x00002aaaab2e1f61 in buf_zip_decompress (block=0x2aaab4525c40, check=<value optimized out>) at buf/buf0buf.c:1826
#2  0x00002aaaab2e56fe in buf_page_get_gen (space=6, zip_size=16384, offset=107754, rw_latch=1, guess=0x0, mode=10, 
    file=0x2aaaab3b5a0b "./include/btr0btr.ic", line=53, mtr=0x49474350) at buf/buf0buf.c:2234
#3  0x00002aaaab2d9fb7 in btr_pcur_move_to_next_page (cursor=0x494747f0, mtr=0x49474350) at ./include/btr0btr.ic:53
#4  0x00002aaaab378f83 in row_merge_read_clustered_index (trx=0x2f84f450, table=0x2f80df40, old_table=0x19ea4080, 
    new_table=0x19ea4080, index=0x2f890440, files=0x2f87e310, n_index=1, block=0x2aadcd708000) at ./include/btr0pcur.ic:350
#5  0x00002aaaab37a012 in row_merge_build_indexes (trx=0x2f84f450, old_table=0x19ea4080, new_table=0x19ea4080, indexes=0x2f7de120, 
    n_indexes=1, table=0x2f80df40) at row/row0merge.c:2480
#6  0x00002aaaab328bfc in ha_innodb::add_index (this=0x2f819d10, table=0x2f80df40, key_info=0x2f88f8c0, 
    num_of_keys=<value optimized out>) at handler/handler0alter.cc:798
#7  0x00000000006e9010 in mysql_alter_table (thd=0x2aadd006cf70, new_db=0x2f88e858 "wikistat", new_name=0x2f88e4f0 "pages0", 
    create_info=0x494770b0, table_list=0x2f88e528, alter_info=0x49477190, order_num=0, order=0x0, ignore=false)
---Type <return> to continue, or q <return> to quit---
    at sql_table.cc:7202
#8  0x00000000005f084a in mysql_execute_command (thd=0x2aadd006cf70) at sql_parse.cc:2898
#9  0x00000000005f59be in mysql_parse (thd=0x2aadd006cf70, inBuf=0x2f88e430 "alter table pages0 add key (crchash,id)", length=39, 
    found_semicolon=0x49478060) at sql_parse.cc:5970
#10 0x00000000005f68ae in dispatch_command (command=COM_QUERY, thd=0x2aadd006cf70, 
    packet=0x2aadd00c8751 "alter table pages0 add key (crchash,id)", packet_length=<value optimized out>) at sql_parse.cc:1231
#11 0x00000000005f7176 in do_command (thd=0x2aadd006cf70) at sql_parse.cc:872
#12 0x00000000005e9ad6 in handle_one_connection (arg=<value optimized out>) at sql_connect.cc:1127
#13 0x00000037e82064a7 in start_thread () from /lib64/libpthread.so.0
#14 0x00000037e7ad3c2d in clone () from /lib64/libc.so.6

Thread 3 (Thread 0x494b9940 (LWP 11200)):
#0  0x00000037e820ab99 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x0000000000621606 in wait_for_condition (thd=0x2aadd00cc760, mutex=0xcdd760, cond=0xcddd60) at sql_base.cc:2169
#2  0x000000000062ad3a in open_table (thd=0x2aadd00cc760, table_list=0x494b8ac0, mem_root=0x494b8320, refresh=0x494b837f, flags=0)
    at sql_base.cc:2834
#3  0x000000000062bb29 in open_tables (thd=0x2aadd00cc760, start=0x494b83c8, counter=0x494b83dc, flags=0) at sql_base.cc:4581
#4  0x000000000062bc9e in open_normal_and_derived_tables (thd=0xcddd64, tables=0x494b8ac0, flags=4294967295) at sql_base.cc:5036
#5  0x00000000006fe182 in mysqld_list_fields (thd=0xcddd64, table_list=0x80, wild=0x2f7e04b8 "") at sql_show.cc:895
#6  0x00000000005f666a in dispatch_command (command=<value optimized out>, thd=0x2aadd00cc760, packet=0x2aadd00cf028 "", 
    packet_length=804458463) at sql_parse.cc:1340
#7  0x00000000005f7176 in do_command (thd=0x2aadd00cc760) at sql_parse.cc:872
#8  0x00000000005e9ad6 in handle_one_connection (arg=<value optimized out>) at sql_connect.cc:1127
#9  0x00000037e82064a7 in start_thread () from /lib64/libpthread.so.0
#10 0x00000037e7ad3c2d in clone () from /lib64/libc.so.6

( I have different table there, but the lock is the same)
[21 Dec 2009 14:30] Sveta Smirnova
Thank you for the report.

Verified as described.

To easily repeat modify sources as follow:

=== modified file 'sql/sql_table.cc'
--- sql/sql_table.cc    2009-11-27 13:34:39 +0000
+++ sql/sql_table.cc    2009-12-21 14:10:24 +0000
@@ -7297,6 +7297,7 @@
     my_free(new_table,MYF(0));
   }
   VOID(pthread_mutex_lock(&LOCK_open));
+  sleep(120);
   if (error)
   {
     VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));

Then start server and run following queries:

create database db1;

use db1;
create table t1(f1 int unsigned not null auto_increment, f2 varchar(2000), f3  int(10) unsigned NOT NULL, PRIMARY KEY(f1)) engine=innodb ROW_FORMAT=COMPRESSED DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8;
--disable_query_log
let $i=400;
while ($i)
{
--eval set @str=repeat(md5($i), 62);
--eval insert into t1(f2,f3) values(@str,$i);
--eval insert into t1(f2,f3) values(@str,$i);
--eval insert into t1(f2,f3) values(@str,$i);
dec $i;
}
--enable_query_log
select now();
alter table t1 add key(f3, f1);

(I use MTR to create data, but this should be not matter,

option file contains:

--innodb_flush_log_at_trx_commit=2 --innodb_flush_method=O_DIRECT --ignore-builtin-innodb --innodb_file_per_table=1 --innodb_file_format=Barracuda --ignore-builtin-innodb --plugin-load=innodb=ha_innodb_plugin.so --plugin-dir=/Users/apple/bzr/mysql-5.1/storage/innodb_plugin/.libs
)

Then in another terminal open new connection, run SHOW PROCESSLIST until you see row like:

|  3 | root | localhost | db1  | Query   |    1 | manage keys | alter table t2 add key(f3, f1) 

Then issue 

USE db1

In third terminal you can see SHOW PROCESSLIST output like in the initial reply:

mysql> show processlist;
+----+------+-----------+------+------------+------+----------------+--------------------------------+
| Id | User | Host      | db   | Command    | Time | State          | Info                           |
+----+------+-----------+------+------------+------+----------------+--------------------------------+
|  2 | root | localhost | db1  | Query      |   57 | manage keys    | alter table t1 add key(f3, f1) |
|  3 | root | localhost | db1  | Field List |   53 | Opening tables |                                |
|  4 | root | localhost | NULL | Query      |    0 | NULL           | show processlist               |
+----+------+-----------+------+------------+------+----------------+--------------------------------+
3 rows in set (0.00 sec)
[1 Jun 2010 7:11] Shane Bester
to repeat:

thread 1:
---------
set old_alter_table=0;
drop table if exists t1;
create table t1(id int not null auto_increment primary key,a char(255) character set latin1)engine=innodb;
insert into t1(a) values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1(a) select t1.a from t1,t1 a,t1 b,t1 c,t1 d,t1 f,t1 g;
alter table t1 add index(a);

thread 2:
---------
select * from t1 limit 10;

thread 3:
---------
show processlist;

+---------+------+-------------------+-----------------------------+
| Command | Time | State             | Info                        |
+---------+------+-------------------+-----------------------------+
| Query   |    5 | manage keys       | alter table t1 add index(a) |
| Query   |    3 | Waiting for table | select * from t1 limit 10   |
| Query   |    0 | NULL              | show processlist            |
+---------+------+-------------------+-----------------------------+
[1 Jun 2010 7:16] Shane Bester
stack traces in a readable format for the above test:

Stack Traces:

mysql> select * from t1 limit 10;

ntdll.dll!_ZwWaitForMultipleObjects@20
kernel32.dll!_WaitForMultipleObjectsEx@20
kernel32.dll!_WaitForMultipleObjects@16
mysqld.exe!pthread_cond_timedwait
mysqld.exe!pthread_cond_wait
mysqld.exe!wait_for_condition
mysqld.exe!open_table
mysqld.exe!open_tables
mysqld.exe!open_and_lock_tables_derived
mysqld.exe!execute_sqlcom_select
mysqld.exe!mysql_execute_command
mysqld.exe!mysql_parse
mysqld.exe!dispatch_command
mysqld.exe!do_command
mysqld.exe!handle_one_connection
mysqld.exe!pthread_start
mysqld.exe!_callthreadstart

mysql> alter table t1 add index(a);

ntdll.dll!_NtWriteFile
kernel32.dll!_WriteFile
ha_innodb_plugin.dll!os_file_write
ha_innodb_plugin.dll!row_merge_write
ha_innodb_plugin.dll!row_merge_write_rec
ha_innodb_plugin.dll!row_merge_blocks
ha_innodb_plugin.dll!row_merge
ha_innodb_plugin.dll!row_merge_sort
ha_innodb_plugin.dll!row_merge_build_indexes
ha_innodb_plugin.dll!ha_innodb::add_index
mysqld.exe!mysql_alter_table
mysqld.exe!mysql_execute_command
mysqld.exe!mysql_parse
mysqld.exe!dispatch_command
mysqld.exe!do_command
mysqld.exe!handle_one_connection
mysqld.exe!pthread_start
mysqld.exe!_callthreadstart
[3 Jun 2010 15:56] Konstantin Osipov
Is it repeatable in 5.5?
Values are low/low for 5.5.
[3 Jun 2010 18:12] Sveta Smirnova
Yes, this is repeatable with next-mr and mysql-trunk-bugfixing.
[9 Nov 2010 13:06] Jon Olav Hauglid
See also bug#42230
[2 Dec 2010 11:48] Jon Olav Hauglid
Setting the bug to patch pending as it is fixed by the patch submitted
(but not yet reviewed) for bug#42230.
[26 Jan 2011 13:51] Jon Olav Hauglid
Closing as a duplicate of Bug#42230

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.047 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.