]> git.pld-linux.org Git - packages/mysql.git/blob - mysql-show_slave_status_nolock.patch
1651c8ad5815a995247dbb7b9dc7463a25416be1
[packages/mysql.git] / mysql-show_slave_status_nolock.patch
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!
8 --- /dev/null
9 +++ b/patch_info/show_slave_status_nolock.patch
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)
17 --- a/sql/lex.h
18 +++ b/sql/lex.h
19 @@ -370,6 +370,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)},
27 --- a/sql/mysqld.cc
28 +++ b/sql/mysqld.cc
29 @@ -3278,6 +3278,7 @@
30    {"show_profiles",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]), 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_statistics",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATS]), SHOW_LONG_STATUS},
37 --- a/sql/sql_lex.h
38 +++ b/sql/sql_lex.h
39 @@ -121,7 +121,8 @@
40    SQLCOM_ALTER_DB_UPGRADE, SQLCOM_SHOW_TEMPORARY_TABLES,
41    SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
42    SQLCOM_SHOW_PATCHES,
43 -
44 +  /* SHOW SLAVE STATUS NOLOCK */
45 +  SQLCOM_SHOW_SLAVE_NOLOCK_STAT,
46    /*
47      When a command is added here, be sure it's also added in mysqld.cc
48      in "struct show_var_st status_vars[]= {" ...
49 --- a/sql/sql_parse.cc
50 +++ b/sql/sql_parse.cc
51 @@ -330,6 +330,7 @@
52    sql_command_flags[SQLCOM_SHOW_CREATE]=  CF_STATUS_COMMAND;
53    sql_command_flags[SQLCOM_SHOW_MASTER_STAT]=  CF_STATUS_COMMAND;
54    sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]=  CF_STATUS_COMMAND;
55 +  sql_command_flags[SQLCOM_SHOW_SLAVE_NOLOCK_STAT]=  CF_STATUS_COMMAND;
56    sql_command_flags[SQLCOM_SHOW_CREATE_PROC]=  CF_STATUS_COMMAND;
57    sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]=  CF_STATUS_COMMAND;
58    sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]=  CF_STATUS_COMMAND;
59 @@ -2596,12 +2597,17 @@
60      pthread_mutex_unlock(&LOCK_active_mi);
61      break;
62    }
63 +  case SQLCOM_SHOW_SLAVE_NOLOCK_STAT:
64    case SQLCOM_SHOW_SLAVE_STAT:
65    {
66      /* Accept one of two privileges */
67      if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
68        goto error;
69 -    pthread_mutex_lock(&LOCK_active_mi);
70 +    bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command;
71 +    if(do_lock)
72 +    {
73 +      pthread_mutex_lock(&LOCK_active_mi);
74 +    }
75      if (active_mi != NULL)
76      {
77        res = show_master_info(thd, active_mi);
78 @@ -2612,7 +2618,19 @@
79                     WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
80        my_ok(thd);
81      }
82 -    pthread_mutex_unlock(&LOCK_active_mi);
83 +    if(do_lock)
84 +    {
85 +      pthread_mutex_unlock(&LOCK_active_mi);
86 +    }
87 +    DBUG_EXECUTE_IF("after_show_slave_status",
88 +                    {
89 +                      const char act[]=
90 +                        "now "
91 +                        "signal signal.after_show_slave_status";
92 +                      DBUG_ASSERT(opt_debug_sync_timeout > 0);
93 +                      DBUG_ASSERT(!debug_sync_set_action(current_thd,
94 +                                                         STRING_WITH_LEN(act)));
95 +                    };);
96      break;
97    }
98    case SQLCOM_SHOW_MASTER_STAT:
99 --- a/sql/sql_yacc.yy
100 +++ b/sql/sql_yacc.yy
101 @@ -1175,6 +1175,7 @@
102  %token  STARTS_SYM
103  %token  START_SYM                     /* SQL-2003-R */
104  %token  STATUS_SYM
105 +%token  NOLOCK_SYM                    /* SHOW SLAVE STATUS NOLOCK */
106  %token  STDDEV_SAMP_SYM               /* SQL-2003-N */
107  %token  STD_SYM
108  %token  STOP_SYM
109 @@ -10387,6 +10388,11 @@
110            {
111              Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
112            }
113 +       /* SHOW SLAVE STATUS NOLOCK */
114 +        | SLAVE STATUS_SYM NOLOCK_SYM
115 +          {
116 +           Lex->sql_command = SQLCOM_SHOW_SLAVE_NOLOCK_STAT; //SQLCOM_SHOW_SLAVE_NOLOCK_STAT;
117 +          }
118          | CLIENT_STATS_SYM wild_and_where 
119            {
120             LEX *lex= Lex;
121 --- /dev/null
122 +++ b/mysql-test/t/percona_show_slave_status_nolock.test
123 @@ -0,0 +1,88 @@
124 +--source include/master-slave.inc
125 +--source include/have_debug_sync.inc
126 +--source include/have_binlog_format_statement.inc
127 +
128 +--let $rpl_connection_name=slave_lock
129 +--let $rpl_server_number=2
130 +--source include/rpl_connect.inc
131 +
132 +--let $rpl_connection_name=slave_nolock
133 +--let $rpl_server_number=2
134 +--source include/rpl_connect.inc
135 +
136 +--let $show_statement= SHOW PROCESSLIST
137 +--let $field= Info
138 +
139 +connection master;
140 +--echo [master]
141 +--disable_warnings
142 +DROP TABLE IF EXISTS t;
143 +--enable_warnings
144 +CREATE TABLE t(id INT);
145 +sync_slave_with_master;
146 +
147 +connection slave;
148 +--echo [slave]
149 +SET DEBUG_SYNC='RESET';
150 +SET GLOBAL DEBUG="+d,after_mysql_insert";
151 +SET GLOBAL DEBUG="+d,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 +DROP TABLE t;
209 +sync_slave_with_master;
210 +
211 +--source include/rpl_end.inc
212 --- /dev/null
213 +++ b/mysql-test/r/percona_show_slave_status_nolock.result
214 @@ -0,0 +1,68 @@
215 +include/master-slave.inc
216 +[connection master]
217 +include/rpl_connect.inc [creating slave_lock]
218 +include/rpl_connect.inc [creating slave_nolock]
219 +[master]
220 +DROP TABLE IF EXISTS t;
221 +CREATE TABLE t(id INT);
222 +[slave]
223 +SET DEBUG_SYNC='RESET';
224 +SET GLOBAL DEBUG="+d,after_mysql_insert";
225 +SET GLOBAL DEBUG="+d,after_show_slave_status";
226 +[master]
227 +INSERT INTO t VALUES(0);
228 +[slave]
229 +check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
230 +
231 +[slave_lock]
232 +SHOW SLAVE STATUS;
233 +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
234 +SIGNAL after SHOW SLAVE STATUS is 'signal.after_show_slave_status'
235 +[slave]
236 +SET DEBUG_SYNC='now SIGNAL signal.empty';
237 +[slave_nolock]
238 +SHOW SLAVE STATUS NOLOCK;
239 +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
240 +# should be 'signal.after_show_slave_status'
241 +SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
242 +[slave]
243 +SET DEBUG_SYNC='now SIGNAL signal.continue';
244 +[slave]
245 +SET DEBUG_SYNC='now SIGNAL signal.empty';
246 +
247 +[master]
248 +INSERT INTO t VALUES(1);
249 +[slave]
250 +include/rpl_connect.inc [creating slave_stop]
251 +[slave_stop]
252 +STOP SLAVE;
253 +[slave]
254 +check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
255 +
256 +[slave_lock]
257 +SHOW SLAVE STATUS;
258 +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
259 +SIGNAL after SHOW SLAVE STATUS is 'signal.empty'
260 +[slave]
261 +SET DEBUG_SYNC='now SIGNAL signal.empty';
262 +[slave_nolock]
263 +SHOW SLAVE STATUS NOLOCK;
264 +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
265 +# should be 'signal.after_show_slave_status'
266 +SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
267 +[slave]
268 +SET DEBUG_SYNC='now SIGNAL signal.continue';
269 +[slave]
270 +SET DEBUG_SYNC='now SIGNAL signal.empty';
271 +
272 +[slave_stop]
273 +include/wait_for_slave_to_stop.inc
274 +START SLAVE;
275 +include/wait_for_slave_to_start.inc
276 +[master]
277 +SET DEBUG_SYNC='RESET';
278 +[slave]
279 +SET GLOBAL DEBUG='';
280 +SET DEBUG_SYNC='RESET';
281 +DROP TABLE t;
282 +include/rpl_end.inc
283 --- /dev/null
284 +++ b/mysql-test/include/percona_show_slave_status_nolock.inc
285 @@ -0,0 +1,56 @@
286 +--echo
287 +--disable_result_log
288 +connection slave_lock;
289 +--echo [slave_lock]
290 +send SHOW SLAVE STATUS;
291 +
292 +connection slave;
293 +--let $condition= 'SHOW SLAVE STATUS'
294 +--source include/wait_show_condition.inc
295 +
296 +--disable_warnings
297 +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
298 +--enable_warnings
299 +
300 +--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'`
301 +--echo SIGNAL after SHOW SLAVE STATUS is $current
302 +
303 +connection slave;
304 +--echo [slave]
305 +SET DEBUG_SYNC='now SIGNAL signal.empty';
306 +
307 +connection slave_nolock;
308 +--echo [slave_nolock]
309 +send SHOW SLAVE STATUS NOLOCK;
310 +
311 +connection slave;
312 +--let $condition= 'SHOW SLAVE STATUS NOLOCK'
313 +--source include/wait_show_condition.inc
314 +
315 +--disable_warnings
316 +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
317 +--enable_warnings
318 +
319 +--echo # should be 'signal.after_show_slave_status'
320 +--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'`
321 +--echo SIGNAL after SHOW SLAVE STATUS NOLOCK is $current
322 +
323 +connection slave;
324 +--echo [slave]
325 +SET DEBUG_SYNC='now SIGNAL signal.continue';
326 +
327 +connection slave_lock;
328 +--disable_result_log
329 +reap;
330 +--enable_result_log
331 +
332 +connection slave_nolock;
333 +--disable_result_log
334 +reap;
335 +--enable_result_log
336 +
337 +connection slave;
338 +--echo [slave]
339 +SET DEBUG_SYNC='now SIGNAL signal.empty';
340 +--enable_result_log
341 +--echo
342 --- a/sql/slave.cc
343 +++ b/sql/slave.cc
344 @@ -1641,6 +1641,7 @@
345  
346    if (mi->host[0])
347    {
348 +    bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != thd->lex->sql_command;
349      DBUG_PRINT("info",("host is set: '%s'", mi->host));
350      String *packet= &thd->packet;
351      protocol->prepare_for_resend();
352 @@ -1649,9 +1650,15 @@
353        slave_running can be accessed without run_lock but not other
354        non-volotile members like mi->io_thd, which is guarded by the mutex.
355      */
356 -    pthread_mutex_lock(&mi->run_lock);
357 +    if (do_lock)
358 +    {
359 +      pthread_mutex_lock(&mi->run_lock);
360 +    }
361      protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin);
362 -    pthread_mutex_unlock(&mi->run_lock);
363 +    if (do_lock)
364 +    {
365 +      pthread_mutex_unlock(&mi->run_lock);
366 +    }
367  
368      pthread_mutex_lock(&mi->data_lock);
369      pthread_mutex_lock(&mi->rli.data_lock);
This page took 0.077907 seconds and 2 git commands to generate.