Bug #44080 Concurrent --send does not get executed every time
Submitted: 3 Apr 2009 17:47 Modified: 26 May 2009 18:12
Reporter: Hakan Küçükyılmaz Email Updates:
Status: Not a Bug Impact on me:
None 
Category:Tools: MTR / mysql-test-run Severity:S7 (Test Cases)
Version:6.0.10 OS:Any
Assigned to: Matthias Leich CPU Architecture:Any

[3 Apr 2009 17:47] Hakan Küçükyılmaz
Description:
A concurrent --send does not get executed every time

How to repeat:
Consider this test:

#
# Testing concurrency behavior of --send
#
--echo *** Concurrency of --send ***

# ----------------------------------------------------- #
# --- Initialisation                                --- #
# ----------------------------------------------------- #

--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings

CREATE TABLE t1 (a int auto_increment primary key, b int);

--echo # Establish connection conn1 (user = root)
connect (conn1,localhost,root,,);

# ----------------------------------------------------- #
# --- Test                                          --- #
# ----------------------------------------------------- #
--echo # Switch to connection default
connection default;
--send INSERT INTO t1 VALUES (DEFAULT, 1)

--echo # Switch to connection conn1
connection conn1;
# If this INSERT gets executed before the --send one, then
# we would have a = 1, b = 2.
INSERT INTO t1 VALUES (DEFAULT, 2);

--echo # Switch to connection default
connection default;
--reap
SELECT a, b FROM t1 ORDER BY a;

# ----------------------------------------------------- #
# --- Check                                         --- #
# ----------------------------------------------------- #
SELECT count(*) FROM t1;

# ----------------------------------------------------- #
# --- Final cleanup                                 --- #
# ----------------------------------------------------- #
DROP TABLE t1;

Expected output:
SELECT a, b FROM t1 ORDER BY a;
a       b
1       1
2       2

Actual outputs:

The second statement can be executed before the
first one. And more surprising: statement two
doesn't get executed at all (sometimes).

This is the failures I get:
falcon.falcon_send_concurrency           [ pass ]      2
falcon.falcon_send_concurrency           [ fail ]
        Test ended at 2009-03-27 23:50:16

CURRENT_TEST: falcon.falcon_send_concurrency
--- /home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/suite/falcon/r/falcon_send_concurrency.result     2009-03-28 01:48:48.000000000 +0300
+++ /home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/suite/falcon/r/falcon_send_concurrency.reject     2009-03-28 01:50:16.000000000 +0300
@@ -10,8 +10,7 @@
 SELECT a, b FROM t1 ORDER BY a;
 a      b
 1      1
-2      2
 SELECT count(*) FROM t1;
 count(*)
-2
+1
 DROP TABLE t1;

mysqltest: Result length mismatch

 - saving
'/home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/var/log/falcon.falcon_send_concurrency/' to '/home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/var/log/falcon.falcon_send_concurrency/'

Retrying test, attempt(2/3)...

falcon.falcon_send_concurrency           [ retry-pass ]      2

Retrying test, attempt(3/3)...

falcon.falcon_send_concurrency           [ retry-fail ]
        Test ended at 2009-03-27 23:50:16

CURRENT_TEST: falcon.falcon_send_concurrency
--- /home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/suite/falcon/r/falcon_send_concurrency.result     2009-03-28 01:48:48.000000000 +0300
+++ /home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/suite/falcon/r/falcon_send_concurrency.reject     2009-03-28 01:50:16.000000000 +0300
@@ -10,8 +10,7 @@
 SELECT a, b FROM t1 ORDER BY a;
 a      b
 1      1
-2      2
 SELECT count(*) FROM t1;
 count(*)
-2
+1
 DROP TABLE t1;

mysqltest: Result length mismatch

 - saving
'/home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/var/log/falcon.falcon_send_concurrency/' to '/home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/var/log/falcon.falcon_send_concurrency/'
falcon.falcon_send_concurrency           [ pass ]      1
falcon.falcon_send_concurrency           [ pass ]      1
falcon.falcon_send_concurrency           [ pass ]      2
falcon.falcon_send_concurrency           [ fail ]
        Test ended at 2009-03-27 23:50:17

CURRENT_TEST: falcon.falcon_send_concurrency
--- /home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/suite/falcon/r/falcon_send_concurrency.result     2009-03-28 01:48:48.000000000 +0300
+++ /home/hakan/work/mysql/mysql-6.0-falcon-team/mysql-test/suite/falcon/r/falcon_send_concurrency.reject     2009-03-28 01:50:17.000000000 +0300
@@ -9,8 +9,8 @@
 # Switch to connection default
 SELECT a, b FROM t1 ORDER BY a;
 a      b
-1      1
-2      2
+1      2
+2      1
 SELECT count(*) FROM t1;
 count(*)
 2
[3 Apr 2009 17:57] Philip Stoev
If you do not move back to connection default after running the second INSERT, the issue does not occur.
[7 Apr 2009 13:49] Bjørn Munch
This is not related to send. I've been able to reproduce the apparently missing INSERT by this simpler test:

--------------
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings

CREATE TABLE t1 (a int primary key, b int);

--echo # Establish connection conn1 (user = root)
connect (conn1,localhost,root,,);

--echo # Switch to connection default
connection default;

--echo # Switch to connection conn1
connection conn1;
INSERT INTO t1 VALUES (2, 2);

--echo # Switch to connection default
connection default;
SELECT * FROM t1;

DROP TABLE t1;
-----------------

I was only able to reproduce this on Linux and only when running some concurrent load (not just any load either, but I've found one that works on that box). Then in roughly 1/250 runs, the SELECT does not see the inserted tuple.

Note that I switch connection twice before the INSERT, if I do it only once, I don't see the problem.
[7 Apr 2009 15:57] Magnus Blåudd
Good! you removed both the auto_increment and send.

Two additional ideas:
1. If the SELECT does not see the INSERT, do SELECT in a loop to see if the rows appears later on. If so after how many loops?
2. Create a third connection "conn2" and swap between that and "conn1"
3. Transaction isolation level? http://dev.mysql.com/doc/refman/5.1/en/set-transaction.html
[13 May 2009 20:29] Hakan Küçükyılmaz
Transaction isolation level is not involved. I run my original test with MyISAM.
[26 May 2009 18:05] Matthias Leich
Bjorn, please excuse that I steal this bug.
[26 May 2009 18:12] Matthias Leich
This is IMHO no bug of mysqltest at all.

The reason is that MySAM runs with
@@global.concurrent_insert <> 0.
The default for this variable is 1 (=enabled).
http://dev.mysql.com/doc/refman/6.0/en/concurrent-inserts.html
IMHO concurrent_insert <> 0
- is a nice feature to accelerate applications using
  MyISAM under some circumstances
- could have a horrible impact on tests if the
  author was not aware of this feature.

I fixed a lot of weak tests by setting concurrent_insert to 0.

Experiments on my notebook, no significant parallel load:
---------------------------------------------------------
export MTR_BUILD_THREAD=260
### ml005 is just the test of Bjorn ###
./mtr --mem --force --repeat=100 --max-test-fail=0 \
    --retry=0 ml005 | tee  ml005.prt 2>&1
grep '\[ fail \]' ml005.prt | wc -l
26
grep '\[ pass \]' ml005.prt | wc -l
74

### ml004 is the test of Bjorn with additional
### @@global.concurrent_insert = 0
./mtr --mem --force --repeat=100 --max-test-fail=0 \
    --retry=0 ml004 | tee  ml004.prt 2>&1
grep '\[ fail \]' ml004.prt | wc -l
0
grep '\[ pass \]' ml004.prt | wc -l
100

Code of ml004.test:
-------------------
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings

CREATE TABLE t1 (a int primary key, b int);

set @global_concurrent_insert = @@global.concurrent_insert;
set @@global.concurrent_insert=0;

--echo # Establish connection conn1 (user = root)
connect (conn1,localhost,root,,);

--echo # Switch to connection default
connection default;

--echo # Switch to connection conn1
connection conn1;
INSERT INTO t1 VALUES (2, 2);

--echo # Switch to connection default
connection default;
SELECT * FROM t1;

DROP TABLE t1;
set @@global.concurrent_insert= @global_concurrent_insert;

=========================================================
BTW: A sufficient long delay between INSERT and the
     critical SELECT would also help.
     Stupid and bad solution: "sleep 3"
     Acceptable solution:
        let $wait_condition= ...
        --source include/wait_condition.inc
       just befor the SELECT.