]>
Commit | Line | Data |
---|---|---|
b4e1fa2c AM |
1 | # name : show_slave_status_nolock.patch |
2 | # introduced : 12 | |
3 | # maintainer : Oleg | |
4 | # | |
5 | #!!! notice !!! | |
6 | # Any small change to this file in the main branch | |
7 | # should be done or reviewed by the maintainer! | |
db82db79 AM |
8 | --- /dev/null |
9 | +++ b/patch_info/show_slave_status_nolock.patch | |
b4e1fa2c AM |
10 | @@ -0,0 +1,6 @@ |
11 | +File=show_slave_status_nolock.patch | |
12 | +Name= SHOW SLAVE STATUS NOLOCK | |
13 | +Version=1.0 | |
14 | +Author=Percona <info@percona.com> | |
15 | +License=GPL | |
16 | +Comment= Implement SHOW SLAVE STATUS without lock (STOP SLAVE lock the same mutex what lock SHOW SLAVE STATUS) | |
db82db79 AM |
17 | --- a/sql/lex.h |
18 | +++ b/sql/lex.h | |
b4e1fa2c AM |
19 | @@ -378,6 +378,7 @@ |
20 | { "NONE", SYM(NONE_SYM)}, | |
21 | { "NOT", SYM(NOT_SYM)}, | |
22 | { "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)}, | |
23 | + { "NOLOCK", SYM(NOLOCK_SYM)}, | |
24 | { "NULL", SYM(NULL_SYM)}, | |
25 | { "NUMERIC", SYM(NUMERIC_SYM)}, | |
26 | { "NVARCHAR", SYM(NVARCHAR_SYM)}, | |
db82db79 AM |
27 | --- a/sql/mysqld.cc |
28 | +++ b/sql/mysqld.cc | |
29ffd636 | 29 | @@ -2971,6 +2971,7 @@ |
b4e1fa2c AM |
30 | {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS}, |
31 | {"show_slave_hosts", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS}, | |
32 | {"show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS}, | |
33 | + {"show_slave_status_nolock", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_NOLOCK_STAT]), SHOW_LONG_STATUS}, | |
34 | {"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS}, | |
35 | {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS}, | |
36 | {"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS}, | |
db82db79 AM |
37 | --- a/sql/sql_lex.h |
38 | +++ b/sql/sql_lex.h | |
b4e1fa2c AM |
39 | @@ -190,6 +190,8 @@ |
40 | SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES, | |
41 | SQLCOM_SIGNAL, SQLCOM_RESIGNAL, | |
42 | SQLCOM_SHOW_RELAYLOG_EVENTS, | |
43 | + /* SHOW SLAVE STATUS NOLOCK */ | |
44 | + SQLCOM_SHOW_SLAVE_NOLOCK_STAT, | |
45 | /* | |
46 | When a command is added here, be sure it's also added in mysqld.cc | |
47 | in "struct show_var_st status_vars[]= {" ... | |
db82db79 AM |
48 | --- a/sql/sql_parse.cc |
49 | +++ b/sql/sql_parse.cc | |
734d6226 | 50 | @@ -336,6 +336,7 @@ |
b4e1fa2c AM |
51 | sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND; |
52 | sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND; | |
53 | sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND; | |
54 | + sql_command_flags[SQLCOM_SHOW_SLAVE_NOLOCK_STAT]= CF_STATUS_COMMAND; | |
55 | sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND; | |
56 | sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND; | |
57 | sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND; | |
13ceb006 | 58 | @@ -2393,12 +2394,17 @@ |
b4e1fa2c AM |
59 | mysql_mutex_unlock(&LOCK_active_mi); |
60 | break; | |
61 | } | |
62 | + case SQLCOM_SHOW_SLAVE_NOLOCK_STAT: | |
63 | case SQLCOM_SHOW_SLAVE_STAT: | |
64 | { | |
65 | /* Accept one of two privileges */ | |
66 | if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) | |
67 | goto error; | |
68 | - mysql_mutex_lock(&LOCK_active_mi); | |
734d6226 AM |
69 | + bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command; |
70 | + if(do_lock) | |
b4e1fa2c AM |
71 | + { |
72 | + mysql_mutex_lock(&LOCK_active_mi); | |
73 | + } | |
74 | if (active_mi != NULL) | |
75 | { | |
76 | res = show_master_info(thd, active_mi); | |
13ceb006 | 77 | @@ -2409,7 +2415,19 @@ |
b4e1fa2c AM |
78 | WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO)); |
79 | my_ok(thd); | |
80 | } | |
81 | - mysql_mutex_unlock(&LOCK_active_mi); | |
734d6226 | 82 | + if(do_lock) |
b4e1fa2c AM |
83 | + { |
84 | + mysql_mutex_unlock(&LOCK_active_mi); | |
85 | + } | |
734d6226 AM |
86 | + DBUG_EXECUTE_IF("after_show_slave_status", |
87 | + { | |
88 | + const char act[]= | |
89 | + "now " | |
90 | + "signal signal.after_show_slave_status"; | |
91 | + DBUG_ASSERT(opt_debug_sync_timeout > 0); | |
92 | + DBUG_ASSERT(!debug_sync_set_action(current_thd, | |
93 | + STRING_WITH_LEN(act))); | |
94 | + };); | |
b4e1fa2c AM |
95 | break; |
96 | } | |
97 | case SQLCOM_SHOW_MASTER_STAT: | |
db82db79 AM |
98 | --- a/sql/sql_yacc.yy |
99 | +++ b/sql/sql_yacc.yy | |
100 | @@ -1293,6 +1293,7 @@ | |
b4e1fa2c AM |
101 | %token STARTS_SYM |
102 | %token START_SYM /* SQL-2003-R */ | |
103 | %token STATUS_SYM | |
104 | +%token NOLOCK_SYM /* SHOW SLAVE STATUS NOLOCK */ | |
105 | %token STDDEV_SAMP_SYM /* SQL-2003-N */ | |
106 | %token STD_SYM | |
107 | %token STOP_SYM | |
29ffd636 | 108 | @@ -11111,6 +11112,11 @@ |
b4e1fa2c AM |
109 | { |
110 | Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; | |
111 | } | |
734d6226 | 112 | + /* SHOW SLAVE STATUS NOLOCK */ |
b4e1fa2c AM |
113 | + | SLAVE STATUS_SYM NOLOCK_SYM |
114 | + { | |
115 | + Lex->sql_command = SQLCOM_SHOW_SLAVE_NOLOCK_STAT; //SQLCOM_SHOW_SLAVE_NOLOCK_STAT; | |
116 | + } | |
117 | | QUERY_RESPONSE_TIME_SYM wild_and_where | |
118 | { | |
119 | #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION | |
48b678b4 | 120 | --- /dev/null |
734d6226 AM |
121 | +++ b/mysql-test/t/percona_show_slave_status_nolock.test |
122 | @@ -0,0 +1,90 @@ | |
123 | +--source include/master-slave.inc | |
124 | +--source include/have_debug_sync.inc | |
125 | +--source include/have_binlog_format_statement.inc | |
126 | + | |
127 | +call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes"); | |
128 | + | |
129 | +--let $rpl_connection_name=slave_lock | |
130 | +--let $rpl_server_number=2 | |
131 | +--source include/rpl_connect.inc | |
132 | + | |
133 | +--let $rpl_connection_name=slave_nolock | |
134 | +--let $rpl_server_number=2 | |
135 | +--source include/rpl_connect.inc | |
136 | + | |
137 | +--let $show_statement= SHOW PROCESSLIST | |
138 | +--let $field= Info | |
139 | + | |
140 | +connection master; | |
141 | +--echo [master] | |
142 | +--disable_warnings | |
143 | +DROP TABLE IF EXISTS t; | |
144 | +--enable_warnings | |
145 | +CREATE TABLE t(id INT); | |
146 | +sync_slave_with_master; | |
147 | + | |
148 | +connection slave; | |
149 | +--echo [slave] | |
150 | +SET DEBUG_SYNC='RESET'; | |
151 | +SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status"; | |
152 | + | |
153 | +connection master; | |
154 | +--echo [master] | |
155 | +INSERT INTO t VALUES(0); | |
156 | + | |
157 | +connection slave; | |
158 | +--echo [slave] | |
159 | +--let $condition= 'INSERT INTO t VALUES(0)' | |
160 | +--source include/wait_show_condition.inc | |
161 | + | |
162 | +--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine | |
163 | +--source include/percona_show_slave_status_nolock.inc | |
164 | + | |
165 | +connection master; | |
166 | +--echo [master] | |
167 | +INSERT INTO t VALUES(1); | |
168 | + | |
169 | +connection slave; | |
170 | +--echo [slave] | |
171 | +--let $condition= 'INSERT INTO t VALUES(1)' | |
172 | +--source include/wait_show_condition.inc | |
173 | + | |
174 | +--let $rpl_connection_name=slave_stop | |
175 | +--let $rpl_server_number=2 | |
176 | +--source include/rpl_connect.inc | |
177 | + | |
178 | +connection slave_stop; | |
179 | +--echo [slave_stop] | |
180 | +send STOP SLAVE; | |
181 | + | |
182 | +connection slave; | |
183 | +--echo [slave] | |
184 | +--let $condition= 'STOP SLAVE' | |
185 | +--source include/wait_show_condition.inc | |
186 | + | |
187 | +--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine | |
188 | +--source include/percona_show_slave_status_nolock.inc | |
189 | + | |
190 | + | |
191 | +connection slave_stop; | |
192 | +--echo [slave_stop] | |
193 | +reap; | |
194 | +--source include/wait_for_slave_to_stop.inc | |
195 | +START SLAVE; | |
196 | +--source include/wait_for_slave_to_start.inc | |
197 | + | |
198 | +connection master; | |
199 | +--echo [master] | |
200 | +SET DEBUG_SYNC='RESET'; | |
201 | + | |
202 | +connection slave; | |
203 | +--echo [slave] | |
204 | +SET GLOBAL DEBUG=''; | |
205 | +SET DEBUG_SYNC='RESET'; | |
206 | + | |
207 | +connection master; | |
208 | +--echo [master] | |
209 | +DROP TABLE t; | |
210 | +sync_slave_with_master; | |
211 | + | |
212 | +--source include/rpl_end.inc | |
213 | --- /dev/null | |
48b678b4 | 214 | +++ b/mysql-test/r/percona_show_slave_status_nolock.result |
734d6226 | 215 | @@ -0,0 +1,69 @@ |
48b678b4 AM |
216 | +include/master-slave.inc |
217 | +[connection master] | |
734d6226 AM |
218 | +call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes"); |
219 | +include/rpl_connect.inc [creating slave_lock] | |
220 | +include/rpl_connect.inc [creating slave_nolock] | |
221 | +[master] | |
48b678b4 AM |
222 | +DROP TABLE IF EXISTS t; |
223 | +CREATE TABLE t(id INT); | |
734d6226 AM |
224 | +[slave] |
225 | +SET DEBUG_SYNC='RESET'; | |
226 | +SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status"; | |
227 | +[master] | |
228 | +INSERT INTO t VALUES(0); | |
229 | +[slave] | |
230 | +check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine | |
231 | + | |
232 | +[slave_lock] | |
233 | +SHOW SLAVE STATUS; | |
234 | +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; | |
235 | +SIGNAL after SHOW SLAVE STATUS is 'signal.after_show_slave_status' | |
236 | +[slave] | |
237 | +SET DEBUG_SYNC='now SIGNAL signal.empty'; | |
238 | +[slave_nolock] | |
239 | +SHOW SLAVE STATUS NOLOCK; | |
240 | +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; | |
241 | +# should be 'signal.after_show_slave_status' | |
242 | +SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status' | |
243 | +[slave] | |
244 | +SET DEBUG_SYNC='now SIGNAL signal.continue'; | |
245 | +[slave] | |
246 | +SET DEBUG_SYNC='now SIGNAL signal.empty'; | |
247 | + | |
248 | +[master] | |
249 | +INSERT INTO t VALUES(1); | |
250 | +[slave] | |
251 | +include/rpl_connect.inc [creating slave_stop] | |
252 | +[slave_stop] | |
48b678b4 | 253 | +STOP SLAVE; |
734d6226 AM |
254 | +[slave] |
255 | +check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine | |
256 | + | |
257 | +[slave_lock] | |
258 | +SHOW SLAVE STATUS; | |
259 | +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; | |
260 | +SIGNAL after SHOW SLAVE STATUS is 'signal.empty' | |
261 | +[slave] | |
262 | +SET DEBUG_SYNC='now SIGNAL signal.empty'; | |
263 | +[slave_nolock] | |
48b678b4 | 264 | +SHOW SLAVE STATUS NOLOCK; |
734d6226 AM |
265 | +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; |
266 | +# should be 'signal.after_show_slave_status' | |
267 | +SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status' | |
268 | +[slave] | |
269 | +SET DEBUG_SYNC='now SIGNAL signal.continue'; | |
270 | +[slave] | |
271 | +SET DEBUG_SYNC='now SIGNAL signal.empty'; | |
272 | + | |
273 | +[slave_stop] | |
48b678b4 AM |
274 | +include/wait_for_slave_to_stop.inc |
275 | +START SLAVE; | |
276 | +include/wait_for_slave_to_start.inc | |
734d6226 AM |
277 | +[master] |
278 | +SET DEBUG_SYNC='RESET'; | |
279 | +[slave] | |
280 | +SET GLOBAL DEBUG=''; | |
281 | +SET DEBUG_SYNC='RESET'; | |
282 | +[master] | |
48b678b4 | 283 | +DROP TABLE t; |
734d6226 | 284 | +include/rpl_end.inc |
48b678b4 | 285 | --- /dev/null |
734d6226 AM |
286 | +++ b/mysql-test/include/percona_show_slave_status_nolock.inc |
287 | @@ -0,0 +1,56 @@ | |
288 | +--echo | |
289 | +--disable_result_log | |
290 | +connection slave_lock; | |
291 | +--echo [slave_lock] | |
292 | +send SHOW SLAVE STATUS; | |
48b678b4 | 293 | + |
734d6226 AM |
294 | +connection slave; |
295 | +--let $condition= 'SHOW SLAVE STATUS' | |
296 | +--source include/wait_show_condition.inc | |
297 | + | |
298 | +--disable_warnings | |
299 | +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; | |
300 | +--enable_warnings | |
301 | + | |
302 | +--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'` | |
303 | +--echo SIGNAL after SHOW SLAVE STATUS is $current | |
48b678b4 AM |
304 | + |
305 | +connection slave; | |
734d6226 AM |
306 | +--echo [slave] |
307 | +SET DEBUG_SYNC='now SIGNAL signal.empty'; | |
48b678b4 | 308 | + |
734d6226 AM |
309 | +connection slave_nolock; |
310 | +--echo [slave_nolock] | |
311 | +send SHOW SLAVE STATUS NOLOCK; | |
48b678b4 | 312 | + |
734d6226 AM |
313 | +connection slave; |
314 | +--let $condition= 'SHOW SLAVE STATUS NOLOCK' | |
315 | +--source include/wait_show_condition.inc | |
48b678b4 | 316 | + |
734d6226 AM |
317 | +--disable_warnings |
318 | +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; | |
319 | +--enable_warnings | |
48b678b4 | 320 | + |
734d6226 AM |
321 | +--echo # should be 'signal.after_show_slave_status' |
322 | +--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'` | |
323 | +--echo SIGNAL after SHOW SLAVE STATUS NOLOCK is $current | |
48b678b4 AM |
324 | + |
325 | +connection slave; | |
734d6226 AM |
326 | +--echo [slave] |
327 | +SET DEBUG_SYNC='now SIGNAL signal.continue'; | |
48b678b4 | 328 | + |
734d6226 AM |
329 | +connection slave_lock; |
330 | +--disable_result_log | |
331 | +reap; | |
332 | +--enable_result_log | |
48b678b4 | 333 | + |
734d6226 AM |
334 | +connection slave_nolock; |
335 | +--disable_result_log | |
336 | +reap; | |
337 | +--enable_result_log | |
48b678b4 | 338 | + |
734d6226 AM |
339 | +connection slave; |
340 | +--echo [slave] | |
341 | +SET DEBUG_SYNC='now SIGNAL signal.empty'; | |
342 | +--enable_result_log | |
343 | +--echo | |
344 | --- a/sql/slave.cc | |
345 | +++ b/sql/slave.cc | |
346 | @@ -1816,6 +1816,7 @@ | |
347 | ||
348 | if (mi->host[0]) | |
349 | { | |
350 | + bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != thd->lex->sql_command; | |
351 | DBUG_PRINT("info",("host is set: '%s'", mi->host)); | |
352 | String *packet= &thd->packet; | |
353 | protocol->prepare_for_resend(); | |
354 | @@ -1824,9 +1825,15 @@ | |
355 | slave_running can be accessed without run_lock but not other | |
356 | non-volotile members like mi->io_thd, which is guarded by the mutex. | |
357 | */ | |
358 | - mysql_mutex_lock(&mi->run_lock); | |
359 | + if (do_lock) | |
360 | + { | |
361 | + mysql_mutex_lock(&mi->run_lock); | |
362 | + } | |
363 | protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin); | |
364 | - mysql_mutex_unlock(&mi->run_lock); | |
365 | + if (do_lock) | |
366 | + { | |
367 | + mysql_mutex_unlock(&mi->run_lock); | |
368 | + } | |
369 | ||
370 | mysql_mutex_lock(&mi->data_lock); | |
371 | mysql_mutex_lock(&mi->rli.data_lock); |