1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
#
# Test of MERGE tables with multisession and many waits.
#
# This test takes rather long time so let us run it only in --big-test mode
--source include/big_test.inc
# We are using some debug-only features in this test
--source include/have_debug.inc
--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6;
--enable_warnings
--echo #
--echo # Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
--echo # corrupts a MERGE table
--echo # Problem #3
--echo #
# Two FLUSH TABLES within a LOCK TABLES segment could invalidate the lock.
# This did *not* require a MERGE table.
#
# To increase reproducibility it was necessary to enter a sleep of 2
# seconds at the end of wait_for_tables() after unlock of LOCK_open. In
# 5.0 and 5.1 the sleep must be inserted in open_and_lock_tables() after
# open_tables() instead. wait_for_tables() is not used in this case. The
# problem was that FLUSH TABLES releases LOCK_open while having unlocked
# and closed all tables. When this happened while a thread was in the
# loop in mysql_lock_tables() right after wait_for_tables()
# (open_tables()) and before retrying to lock, the thread got the lock.
# And it did not notice that the table needed a refresh after the
# [re-]open. So it executed its statement on the table.
#
# The first FLUSH TABLES kicked the INSERT out of thr_multi_lock() and
# let it wait in wait_for_tables() (open_table()). The second FLUSH
# TABLES must happen while the INSERT was on its way from
# wait_for_tables() (open_table()) to the next call of thr_multi_lock().
# This needed to be supported by a sleep to make it repeatable.
#
CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
LOCK TABLE t1 WRITE;
#SELECT NOW();
--echo # connection con1
connect (con1,localhost,root,,);
let $con1_id= `SELECT CONNECTION_ID()`;
SET SESSION debug="+d,sleep_open_and_lock_after_open";
send INSERT INTO t1 VALUES (1);
--echo # connection default
connection default;
--echo # Let INSERT go into thr_multi_lock().
let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE ID = $con1_id AND STATE = 'Locked';
--source include/wait_condition.inc
#SELECT NOW();
--echo # Kick INSERT out of thr_multi_lock().
FLUSH TABLES;
#SELECT NOW();
--echo # Let INSERT go through open_tables() where it sleeps.
let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE ID = $con1_id AND STATE = 'DBUG sleep';
--source include/wait_condition.inc
#SELECT NOW();
--echo # Unlock and close table and wait for con1 to close too.
FLUSH TABLES;
#SELECT NOW();
--echo # This should give no result.
SELECT * FROM t1;
#SELECT NOW();
UNLOCK TABLES;
--echo # connection con1
connection con1;
reap;
SET SESSION debug="-d,sleep_open_and_lock_after_open";
disconnect con1;
--echo # connection default
connection default;
DROP TABLE t1;
--echo #
--echo # Extra tests for Bug#26379 - Combination of FLUSH TABLE and
--echo # REPAIR TABLE corrupts a MERGE table
--echo #
CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c1 INT);
CREATE TABLE t3 (c1 INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
INSERT INTO t3 VALUES (3);
--echo #
--echo # CREATE ... SELECT
--echo # try to access parent from another thread.
--echo #
#SELECT NOW();
--echo # connection con1
connect (con1,localhost,root,,);
let $con1_id= `SELECT CONNECTION_ID()`;
SET SESSION debug="+d,sleep_create_select_before_lock";
send CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
INSERT_METHOD=FIRST SELECT * FROM t3;
--echo # connection default
connection default;
# wait for the other query to start executing
let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE ID = $con1_id AND STATE = 'DBUG sleep';
--source include/wait_condition.inc
#SELECT NOW();
--echo # Now try to access the parent.
--echo # If 3 is in table, SELECT had to wait.
SELECT * FROM t4 ORDER BY c1;
#SELECT NOW();
--echo # connection con1
connection con1;
reap;
#SELECT NOW();
SET SESSION debug="-d,sleep_create_select_before_lock";
disconnect con1;
--echo # connection default
connection default;
--echo # Cleanup for next test.
DROP TABLE t4;
DELETE FROM t1 WHERE c1 != 1;
--echo #
--echo # CREATE ... SELECT
--echo # try to access child from another thread.
--echo #
#SELECT NOW();
--echo # connection con1
connect (con1,localhost,root,,);
let $con1_id= `SELECT CONNECTION_ID()`;
SET SESSION debug="+d,sleep_create_select_before_lock";
send CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
INSERT_METHOD=FIRST SELECT * FROM t3;
--echo # connection default
connection default;
# wait for the other query to start executing
let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE ID = $con1_id AND STATE = 'DBUG sleep';
--source include/wait_condition.inc
#SELECT NOW();
--echo # Now try to access a child.
--echo # If 3 is in table, SELECT had to wait.
SELECT * FROM t1 ORDER BY c1;
#SELECT NOW();
--echo # connection con1
connection con1;
reap;
#SELECT NOW();
SET SESSION debug="-d,sleep_create_select_before_lock";
disconnect con1;
--echo # connection default
connection default;
DROP TABLE t1, t2, t3, t4;
|