Bug #42501 select returns empty set if autocommit=0 after add index in another thread
Submitted: 31 Jan 2009 15:40 Modified: 23 Nov 2009 11:26
Reporter: Andrii Nikitin Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:5.1.30 OS:Any
Assigned to: CPU Architecture:Any

[31 Jan 2009 15:40] Andrii Nikitin
Description:
select returns empty set if autocommit=0 after add/drop index in another thread when innodb_locks_unsafe_for_binlog=1 .

1. Thread 1: set autocommit=0;
2. Thread 1: select * from t => multiple rows
3. Thread 2: alter t add or drop index;
4. Thread 1: select * from t => empty set
5. Thread 1: rollback
6. Thread 1: select * from t => multiple rows again

If autocommit=1 or innodb_locks_unsafe_for_binlog is off or engine is myisam => step 4 returns resultset

Review two sessions scripts below (note timestamp in prompt shows time when previous command finished execution).
It is recommended to repeat scripts on fresh server. (Problem may disappear after several iterations).

======= Thread1 ============

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.1.30-enterprise-gpl-advanced MySQL Enterprise Server - Advanced Edition (GPL)

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

03:34:26(ODBC@localhost)[(none)]>select version();
+--------------------------------+
| version()                      |
+--------------------------------+
| 5.1.30-enterprise-gpl-advanced |
+--------------------------------+
1 row in set (0.01 sec)

03:34:34(ODBC@localhost)[(none)]>drop database test;
Query OK, 1 row affected (0.00 sec)

03:34:49(ODBC@localhost)[(none)]>create database test;
Query OK, 1 row affected (0.02 sec)

03:35:10(ODBC@localhost)[(none)]>set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

03:35:34(ODBC@localhost)[(none)]>select * from t;
ERROR 1046 (3D000): No database selected
03:36:33(ODBC@localhost)[(none)]>use test;
Database changed
03:36:37(ODBC@localhost)[test]>select * from t;
+---+------+
| a | b    |
+---+------+
| 1 |    2 |
| 2 |    3 |
| 3 |    2 |
| 4 |    3 |
| 5 |    2 |
+---+------+
5 rows in set (0.00 sec)

03:36:38(ODBC@localhost)[test]>select * from t;
Empty set (0.00 sec)

03:37:00(ODBC@localhost)[test]>select SQL_NO_CACHE * from t;
Empty set (0.00 sec)

03:37:07(ODBC@localhost)[test]>rollback;
Query OK, 0 rows affected (0.00 sec)

03:37:14(ODBC@localhost)[test]>select * from t;
+---+------+
| a | b    |
+---+------+
| 1 |    2 |
| 2 |    3 |
| 3 |    2 |
| 4 |    3 |
| 5 |    2 |
+---+------+
5 rows in set (0.00 sec)

03:37:17(ODBC@localhost)[test]>

=========== Thread 2 =================

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.1.30-enterprise-gpl-advanced MySQL Enterprise Server - Advanced Edition (GPL)

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

03:34:23(root@localhost)[(none)]>use test;
ERROR 1049 (42000): Unknown database 'test'
03:35:02(root@localhost)[(none)]>use test;
Database changed
03:35:11(root@localhost)[test]>set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

03:35:46(root@localhost)[test]>CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB;
Query OK, 0 rows affected (0.02 sec)

03:36:15(root@localhost)[test]>INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2);
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

03:36:15(root@localhost)[test]>COMMIT;
Query OK, 0 rows affected (0.00 sec)

03:36:15(root@localhost)[test]>select * from t;
+---+------+
| a | b    |
+---+------+
| 1 |    2 |
| 2 |    3 |
| 3 |    2 |
| 4 |    3 |
| 5 |    2 |
+---+------+
5 rows in set (0.00 sec)

03:36:26(root@localhost)[test]>alter table t add index ib(b);
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

03:36:52(root@localhost)[test]>select * from t;
+---+------+
| a | b    |
+---+------+
| 1 |    2 |
| 2 |    3 |
| 3 |    2 |
| 4 |    3 |
| 5 |    2 |
+---+------+
5 rows in set (0.00 sec)

03:36:57(root@localhost)[test]>

How to repeat:
1. Configure innodb_locks_unsafe_for_binlog=1 and start server
2. Start mysql1 and execute:

create database bug;
use bug;
create table t(id int) engine=innodb;
insert into t values(1), (2);
set autocommit=0;
select * from t; -- this is important to see the bug!
-- => see expected output

3. start mysql2 and execute:
use bug;
set autocommit=0;
alter table t add index i(id);

4. in mysql1:
select * from t;
-- => empty resultset shown  => bug
rollback;
select * from t;
-- => correct output (1), (2)

Suggested fix:
Return correct data
[31 Jan 2009 16:20] Andrii Nikitin
variable innodb_locks_unsafe_for_binlog doesn't matter. Most important thing is to execute SELECT in first thread before ADD/DROP INDEX in the second. 
(Probably I missed this step when was testing with innodb_locks_unsafe_for_binlog=OFF .)
[31 Jan 2009 16:50] Valeriy Kravchuk
I think this is essentially a duplicate of bug #989. Please, check.
[31 Jan 2009 16:51] Valeriy Kravchuk
Or, even more likely, this is a duplicate of bug #11981...
[1 Mar 2009 0:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[23 Nov 2009 11:26] Andrii Nikitin
duplicate of bug #11981