Merge lp:~tsarev/percona-server/12952 into lp:percona-server/5.1
- 12952
- Merge into 5.1
Status: | Merged |
---|---|
Merged at revision: | 283 |
Proposed branch: | lp:~tsarev/percona-server/12952 |
Merge into: | lp:percona-server/5.1 |
Diff against target: |
364 lines (+250/-68) 1 file modified
patches/show_slave_status_nolock.patch (+250/-68) |
To merge this branch: | bzr merge lp:~tsarev/percona-server/12952 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexey Kopytov (community) | Approve | ||
Oleg Tsarev | Pending | ||
Review via email: mp+75708@code.launchpad.net |
This proposal supersedes a proposal from 2011-09-16.
Commit message
Description of the change
Add test-case for bug #851011: SHOW SLAVE STATUS NOLOCK acquire lock on
sql/slave.cc: 1650
pthread_
Fix: wrap mutex lock/unlock by check to \"UNLOCK\" statement
Issue number: #12952.
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal | # |
Oleg Tsarev (tsarev) wrote : Posted in a previous version of this proposal | # |
This test-case check feature "SHOW SLAVE STATUS NOLOCK" workability.
Test-case according to issue number 12952 (customer-case).
Result file contain correct result of run, if feature works fine.
Right now this test fails.
> "SHOW SLAVE STATUS NOLOCK acquire lock on some mutex" sounds like the problem is not quite clear.
Fix will ve in another MP, this is just a test-case.
Please note:
What exactly you don't understand or don't like in this MP?
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal | # |
Please submit a MP for the full bugfix including the test case and update the bug report so that it's clear which specific mutex is holding SHOW SLAVE STATUS NOLOCK under what circumstances.
Oleg Tsarev (tsarev) wrote : | # |
For detalise circumstances need additional investigation.
If you think investigation are required - I can complete it.
Oleg Tsarev (tsarev) wrote : | # |
Additional information about circumstances.
1) SHOW SLAVE STATUS [NOLOCK] passed following mutexes:
query: SHOW SLAVE STATUS
| | mutex: 'LOCK_active_mi' lock FILE: sql_parse.cc LINE: 2597
| | | mutex: 'Master_
| | | mutex: 'Master_
| | | mutex: 'Master_
| | | mutex: 'Relay_
| | | mutex: 'Relay_
| | | mutex: 'Master_
| | mutex: 'LOCK_active_mi' unlock FILE: sql_parse.cc LINE: 2608
2) SLAVE SQL THREAD while applying events passed following mutexes:
<apply_
mutex: 'Relay_
>apply_
| mutex: 'Relay_
| | mutex: 'Relay_
| | mutex: 'Relay_
3) STOP SLAVE command passing following mutexes:
query: STOP SLAVE
| | mutex: 'LOCK_active_mi' lock FILE: sql_parse.cc LINE: 3007
| | | | mutex: 'Master_
| | | | mutex: 'Relay_
| | | | | mutex: 'Relay_
# !!! HERE WE WAIT UNTIL COMPLETE QUERY FROM SQL_SLAVE_THREAD !!! #
| | | | | mutex: 'Relay_
| | | | | mutex: 'Master_
| | | | | mutex: 'Master_
| | | | mutex: 'Relay_
| | | | mutex: 'Master_
| | mutex: 'LOCK_active_mi' unlock FILE: sql_parse.cc LINE: 3009
As we can see, STOP SLAVE lock following mutexes:
1) 'LOCK_active_mi' FILE: sql_parse.cc LINE: 3007
2) 'Master_
mutex 'Relay_
As result, SHOW SLAVE STATUS NOLOCK should not lock this two mutexes (wrapped by check in the my fix).
I hope, this information enough for your understanding of circumstances.
If you need any additional information - I can provide it for you (just highligh what you want know).
Alexey Kopytov (akopytov) wrote : | # |
Approved if passes Jenkins. Please also port to 5.5.
Preview Diff
1 | === modified file 'patches/show_slave_status_nolock.patch' |
2 | --- patches/show_slave_status_nolock.patch 2011-09-06 08:23:51 +0000 |
3 | +++ patches/show_slave_status_nolock.patch 2011-09-16 10:56:26 +0000 |
4 | @@ -56,7 +56,7 @@ |
5 | sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND; |
6 | sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND; |
7 | sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND; |
8 | -@@ -2589,12 +2590,16 @@ |
9 | +@@ -2591,12 +2592,17 @@ |
10 | pthread_mutex_unlock(&LOCK_active_mi); |
11 | break; |
12 | } |
13 | @@ -67,22 +67,32 @@ |
14 | if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) |
15 | goto error; |
16 | - pthread_mutex_lock(&LOCK_active_mi); |
17 | -+ if(SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command) |
18 | ++ bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command; |
19 | ++ if(do_lock) |
20 | + { |
21 | + pthread_mutex_lock(&LOCK_active_mi); |
22 | + } |
23 | if (active_mi != NULL) |
24 | { |
25 | res = show_master_info(thd, active_mi); |
26 | -@@ -2605,7 +2610,10 @@ |
27 | +@@ -2607,7 +2613,19 @@ |
28 | WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO)); |
29 | my_ok(thd); |
30 | } |
31 | - pthread_mutex_unlock(&LOCK_active_mi); |
32 | -+ if(SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command) |
33 | ++ if(do_lock) |
34 | + { |
35 | + pthread_mutex_unlock(&LOCK_active_mi); |
36 | + } |
37 | ++ DBUG_EXECUTE_IF("after_show_slave_status", |
38 | ++ { |
39 | ++ const char act[]= |
40 | ++ "now " |
41 | ++ "signal signal.after_show_slave_status"; |
42 | ++ DBUG_ASSERT(opt_debug_sync_timeout > 0); |
43 | ++ DBUG_ASSERT(!debug_sync_set_action(current_thd, |
44 | ++ STRING_WITH_LEN(act))); |
45 | ++ };); |
46 | break; |
47 | } |
48 | case SQLCOM_SHOW_MASTER_STAT: |
49 | @@ -109,79 +119,251 @@ |
50 | { |
51 | LEX *lex= Lex; |
52 | --- /dev/null |
53 | ++++ b/mysql-test/t/percona_show_slave_status_nolock.test |
54 | +@@ -0,0 +1,88 @@ |
55 | ++--source include/master-slave.inc |
56 | ++--source include/have_debug_sync.inc |
57 | ++--source include/have_binlog_format_statement.inc |
58 | ++ |
59 | ++--let $rpl_connection_name=slave_lock |
60 | ++--let $rpl_server_number=2 |
61 | ++--source include/rpl_connect.inc |
62 | ++ |
63 | ++--let $rpl_connection_name=slave_nolock |
64 | ++--let $rpl_server_number=2 |
65 | ++--source include/rpl_connect.inc |
66 | ++ |
67 | ++--let $show_statement= SHOW PROCESSLIST |
68 | ++--let $field= Info |
69 | ++ |
70 | ++connection master; |
71 | ++--echo [master] |
72 | ++--disable_warnings |
73 | ++DROP TABLE IF EXISTS t; |
74 | ++--enable_warnings |
75 | ++CREATE TABLE t(id INT); |
76 | ++sync_slave_with_master; |
77 | ++ |
78 | ++connection slave; |
79 | ++--echo [slave] |
80 | ++SET DEBUG_SYNC='RESET'; |
81 | ++SET GLOBAL DEBUG="+d,after_mysql_insert"; |
82 | ++SET GLOBAL DEBUG="+d,after_show_slave_status"; |
83 | ++ |
84 | ++connection master; |
85 | ++--echo [master] |
86 | ++INSERT INTO t VALUES(0); |
87 | ++ |
88 | ++connection slave; |
89 | ++--echo [slave] |
90 | ++--let $condition= 'INSERT INTO t VALUES(0)' |
91 | ++--source include/wait_show_condition.inc |
92 | ++ |
93 | ++--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine |
94 | ++--source include/percona_show_slave_status_nolock.inc |
95 | ++ |
96 | ++connection master; |
97 | ++--echo [master] |
98 | ++INSERT INTO t VALUES(1); |
99 | ++ |
100 | ++connection slave; |
101 | ++--echo [slave] |
102 | ++--let $condition= 'INSERT INTO t VALUES(1)' |
103 | ++--source include/wait_show_condition.inc |
104 | ++ |
105 | ++--let $rpl_connection_name=slave_stop |
106 | ++--let $rpl_server_number=2 |
107 | ++--source include/rpl_connect.inc |
108 | ++ |
109 | ++connection slave_stop; |
110 | ++--echo [slave_stop] |
111 | ++send STOP SLAVE; |
112 | ++ |
113 | ++connection slave; |
114 | ++--echo [slave] |
115 | ++--let $condition= 'STOP SLAVE' |
116 | ++--source include/wait_show_condition.inc |
117 | ++ |
118 | ++--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine |
119 | ++--source include/percona_show_slave_status_nolock.inc |
120 | ++ |
121 | ++ |
122 | ++connection slave_stop; |
123 | ++--echo [slave_stop] |
124 | ++reap; |
125 | ++--source include/wait_for_slave_to_stop.inc |
126 | ++START SLAVE; |
127 | ++--source include/wait_for_slave_to_start.inc |
128 | ++ |
129 | ++connection master; |
130 | ++--echo [master] |
131 | ++SET DEBUG_SYNC='RESET'; |
132 | ++ |
133 | ++connection slave; |
134 | ++--echo [slave] |
135 | ++SET GLOBAL DEBUG=''; |
136 | ++SET DEBUG_SYNC='RESET'; |
137 | ++ |
138 | ++connection master; |
139 | ++DROP TABLE t; |
140 | ++sync_slave_with_master; |
141 | ++ |
142 | ++--source include/rpl_end.inc |
143 | +--- /dev/null |
144 | +++ b/mysql-test/r/percona_show_slave_status_nolock.result |
145 | -@@ -0,0 +1,21 @@ |
146 | +@@ -0,0 +1,68 @@ |
147 | +include/master-slave.inc |
148 | +[connection master] |
149 | ++include/rpl_connect.inc [creating slave_lock] |
150 | ++include/rpl_connect.inc [creating slave_nolock] |
151 | ++[master] |
152 | +DROP TABLE IF EXISTS t; |
153 | +CREATE TABLE t(id INT); |
154 | -+INSERT INTO t SELECT SLEEP(10); |
155 | ++[slave] |
156 | ++SET DEBUG_SYNC='RESET'; |
157 | ++SET GLOBAL DEBUG="+d,after_mysql_insert"; |
158 | ++SET GLOBAL DEBUG="+d,after_show_slave_status"; |
159 | ++[master] |
160 | ++INSERT INTO t VALUES(0); |
161 | ++[slave] |
162 | ++check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine |
163 | ++ |
164 | ++[slave_lock] |
165 | ++SHOW SLAVE STATUS; |
166 | ++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; |
167 | ++SIGNAL after SHOW SLAVE STATUS is 'signal.after_show_slave_status' |
168 | ++[slave] |
169 | ++SET DEBUG_SYNC='now SIGNAL signal.empty'; |
170 | ++[slave_nolock] |
171 | ++SHOW SLAVE STATUS NOLOCK; |
172 | ++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; |
173 | ++# should be 'signal.after_show_slave_status' |
174 | ++SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status' |
175 | ++[slave] |
176 | ++SET DEBUG_SYNC='now SIGNAL signal.continue'; |
177 | ++[slave] |
178 | ++SET DEBUG_SYNC='now SIGNAL signal.empty'; |
179 | ++ |
180 | ++[master] |
181 | ++INSERT INTO t VALUES(1); |
182 | ++[slave] |
183 | ++include/rpl_connect.inc [creating slave_stop] |
184 | ++[slave_stop] |
185 | +STOP SLAVE; |
186 | -+Warnings: |
187 | -+Note 1592 Statement may not be safe to log in statement format. |
188 | -+master count(*) |
189 | -+master 1 |
190 | -+slave count(*) |
191 | -+slave 0 |
192 | ++[slave] |
193 | ++check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine |
194 | ++ |
195 | ++[slave_lock] |
196 | ++SHOW SLAVE STATUS; |
197 | ++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; |
198 | ++SIGNAL after SHOW SLAVE STATUS is 'signal.empty' |
199 | ++[slave] |
200 | ++SET DEBUG_SYNC='now SIGNAL signal.empty'; |
201 | ++[slave_nolock] |
202 | +SHOW SLAVE STATUS NOLOCK; |
203 | ++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; |
204 | ++# should be 'signal.after_show_slave_status' |
205 | ++SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status' |
206 | ++[slave] |
207 | ++SET DEBUG_SYNC='now SIGNAL signal.continue'; |
208 | ++[slave] |
209 | ++SET DEBUG_SYNC='now SIGNAL signal.empty'; |
210 | ++ |
211 | ++[slave_stop] |
212 | +include/wait_for_slave_to_stop.inc |
213 | +START SLAVE; |
214 | +include/wait_for_slave_to_start.inc |
215 | -+slave count(*) |
216 | -+slave 1 |
217 | ++[master] |
218 | ++SET DEBUG_SYNC='RESET'; |
219 | ++[slave] |
220 | ++SET GLOBAL DEBUG=''; |
221 | ++SET DEBUG_SYNC='RESET'; |
222 | +DROP TABLE t; |
223 | -+STOP SLAVE; |
224 | -+include/wait_for_slave_to_stop.inc |
225 | ++include/rpl_end.inc |
226 | --- /dev/null |
227 | -+++ b/mysql-test/t/percona_show_slave_status_nolock.test |
228 | -@@ -0,0 +1,50 @@ |
229 | -+--source include/master-slave.inc |
230 | -+--source include/have_binlog_format_statement.inc |
231 | -+ |
232 | -+connection master; |
233 | -+ --disable_warnings |
234 | -+ DROP TABLE IF EXISTS t; |
235 | -+ --enable_warnings |
236 | -+ CREATE TABLE t(id INT); |
237 | -+ sync_slave_with_master; |
238 | -+ |
239 | -+connection master; |
240 | -+ send INSERT INTO t SELECT SLEEP(10); |
241 | -+ |
242 | -+connection slave; |
243 | -+ sleep 15; |
244 | -+ send STOP SLAVE; |
245 | -+ |
246 | -+connection master; |
247 | -+ reap; |
248 | -+ |
249 | -+ --disable_query_log |
250 | -+ select "master",count(*) from t; |
251 | -+ --enable_query_log |
252 | -+ |
253 | -+connection slave1; |
254 | -+ --disable_query_log |
255 | -+ select "slave",count(*) from t; |
256 | -+ --enable_query_log |
257 | -+ |
258 | -+ --disable_result_log |
259 | -+ SHOW SLAVE STATUS NOLOCK; |
260 | -+ --enable_result_log |
261 | -+ |
262 | -+connection slave; |
263 | -+ reap; |
264 | -+ |
265 | -+ --source include/wait_for_slave_to_stop.inc |
266 | -+ START SLAVE; |
267 | -+ --source include/wait_for_slave_to_start.inc |
268 | -+ |
269 | -+ --disable_query_log |
270 | -+ select "slave",count(*) from t; |
271 | -+ --enable_query_log |
272 | -+ |
273 | -+connection master; |
274 | -+ DROP TABLE t; |
275 | -+sync_slave_with_master; |
276 | -+ |
277 | -+STOP SLAVE; |
278 | -+--source include/wait_for_slave_to_stop.inc |
279 | ++++ b/mysql-test/include/percona_show_slave_status_nolock.inc |
280 | +@@ -0,0 +1,56 @@ |
281 | ++--echo |
282 | ++--disable_result_log |
283 | ++connection slave_lock; |
284 | ++--echo [slave_lock] |
285 | ++send SHOW SLAVE STATUS; |
286 | ++ |
287 | ++connection slave; |
288 | ++--let $condition= 'SHOW SLAVE STATUS' |
289 | ++--source include/wait_show_condition.inc |
290 | ++ |
291 | ++--disable_warnings |
292 | ++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; |
293 | ++--enable_warnings |
294 | ++ |
295 | ++--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'` |
296 | ++--echo SIGNAL after SHOW SLAVE STATUS is $current |
297 | ++ |
298 | ++connection slave; |
299 | ++--echo [slave] |
300 | ++SET DEBUG_SYNC='now SIGNAL signal.empty'; |
301 | ++ |
302 | ++connection slave_nolock; |
303 | ++--echo [slave_nolock] |
304 | ++send SHOW SLAVE STATUS NOLOCK; |
305 | ++ |
306 | ++connection slave; |
307 | ++--let $condition= 'SHOW SLAVE STATUS NOLOCK' |
308 | ++--source include/wait_show_condition.inc |
309 | ++ |
310 | ++--disable_warnings |
311 | ++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; |
312 | ++--enable_warnings |
313 | ++ |
314 | ++--echo # should be 'signal.after_show_slave_status' |
315 | ++--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'` |
316 | ++--echo SIGNAL after SHOW SLAVE STATUS NOLOCK is $current |
317 | ++ |
318 | ++connection slave; |
319 | ++--echo [slave] |
320 | ++SET DEBUG_SYNC='now SIGNAL signal.continue'; |
321 | ++ |
322 | ++connection slave_lock; |
323 | ++--disable_result_log |
324 | ++reap; |
325 | ++--enable_result_log |
326 | ++ |
327 | ++connection slave_nolock; |
328 | ++--disable_result_log |
329 | ++reap; |
330 | ++--enable_result_log |
331 | ++ |
332 | ++connection slave; |
333 | ++--echo [slave] |
334 | ++SET DEBUG_SYNC='now SIGNAL signal.empty'; |
335 | ++--enable_result_log |
336 | ++--echo |
337 | +--- a/sql/slave.cc |
338 | ++++ b/sql/slave.cc |
339 | +@@ -1639,6 +1639,7 @@ |
340 | + |
341 | + if (mi->host[0]) |
342 | + { |
343 | ++ bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != thd->lex->sql_command; |
344 | + DBUG_PRINT("info",("host is set: '%s'", mi->host)); |
345 | + String *packet= &thd->packet; |
346 | + protocol->prepare_for_resend(); |
347 | +@@ -1647,9 +1648,15 @@ |
348 | + slave_running can be accessed without run_lock but not other |
349 | + non-volotile members like mi->io_thd, which is guarded by the mutex. |
350 | + */ |
351 | +- pthread_mutex_lock(&mi->run_lock); |
352 | ++ if (do_lock) |
353 | ++ { |
354 | ++ pthread_mutex_lock(&mi->run_lock); |
355 | ++ } |
356 | + protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin); |
357 | +- pthread_mutex_unlock(&mi->run_lock); |
358 | ++ if (do_lock) |
359 | ++ { |
360 | ++ pthread_mutex_unlock(&mi->run_lock); |
361 | ++ } |
362 | + |
363 | + pthread_mutex_lock(&mi->data_lock); |
364 | + pthread_mutex_lock(&mi->rli.data_lock); |
I don't see a point in reviewing a test case separately from the fix. For example, is the .result file from the test with the bug fixed or not?
And I still don't see a detailed description of the problem we are trying to fix, which complicates reviewing the test case even further. No, the reported bug does not help much either. "SHOW SLAVE STATUS NOLOCK acquire lock on some mutex" sounds like the problem is not quite clear.