MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sql_reload.cc
1 /* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include "sql_reload.h"
17 #include "sql_priv.h"
18 #include "mysqld.h" // select_errors
19 #include "sql_class.h" // THD
20 #include "sql_acl.h" // acl_reload
21 #include "sql_servers.h" // servers_reload
22 #include "sql_connect.h" // reset_mqh
23 #include "sql_base.h" // close_cached_tables
24 #include "sql_db.h" // my_dbopt_cleanup
25 #include "hostname.h" // hostname_cache_refresh
26 #include "rpl_master.h" // reset_master
27 #include "rpl_slave.h" // reset_slave
28 #include "rpl_rli.h" // rotate_relay_log
29 #include "rpl_mi.h"
30 #include "debug_sync.h"
31 
32 
56 bool reload_acl_and_cache(THD *thd, unsigned long options,
57  TABLE_LIST *tables, int *write_to_binlog)
58 {
59  bool result=0;
60  select_errors=0; /* Write if more errors */
61  int tmp_write_to_binlog= *write_to_binlog= 1;
62 
63  DBUG_ASSERT(!thd || !thd->in_sub_stmt);
64 
65 #ifndef NO_EMBEDDED_ACCESS_CHECKS
66  if (options & REFRESH_GRANT)
67  {
68  THD *tmp_thd= 0;
69  /*
70  If reload_acl_and_cache() is called from SIGHUP handler we have to
71  allocate temporary THD for execution of acl_reload()/grant_reload().
72  */
73  if (!thd && (thd= (tmp_thd= new THD)))
74  {
75  thd->thread_stack= (char*) &tmp_thd;
76  thd->store_globals();
77  }
78 
79  if (thd)
80  {
81  bool reload_acl_failed= acl_reload(thd);
82  bool reload_grants_failed= grant_reload(thd);
83  bool reload_servers_failed= servers_reload(thd);
84 
85  if (reload_acl_failed || reload_grants_failed || reload_servers_failed)
86  {
87  result= 1;
88  /*
89  When an error is returned, my_message may have not been called and
90  the client will hang waiting for a response.
91  */
92  my_error(ER_UNKNOWN_ERROR, MYF(0));
93  }
94  }
95 
96  if (tmp_thd)
97  {
98  delete tmp_thd;
99  /* Remember that we don't have a THD */
100  my_pthread_setspecific_ptr(THR_THD, 0);
101  thd= 0;
102  }
103  reset_mqh((LEX_USER *)NULL, TRUE);
104  }
105 #endif
106  if (options & REFRESH_LOG)
107  {
108  /*
109  Flush the normal query log, the update log, the binary log,
110  the slow query log, the relay log (if it exists) and the log
111  tables.
112  */
113 
114  options|= REFRESH_BINARY_LOG;
115  options|= REFRESH_RELAY_LOG;
116  options|= REFRESH_SLOW_LOG;
117  options|= REFRESH_GENERAL_LOG;
118  options|= REFRESH_ENGINE_LOG;
119  options|= REFRESH_ERROR_LOG;
120  }
121 
122  if (options & REFRESH_ERROR_LOG)
123  if (flush_error_log())
124  {
125  /*
126  When flush_error_log() failed, my_error() has not been called.
127  So, we have to do it here to keep the protocol.
128  */
129  my_error(ER_UNKNOWN_ERROR, MYF(0));
130  result= 1;
131  }
132 
133  if ((options & REFRESH_SLOW_LOG) && opt_slow_log)
134  logger.flush_slow_log();
135 
136  if ((options & REFRESH_GENERAL_LOG) && opt_log)
137  logger.flush_general_log();
138 
139  if (options & REFRESH_ENGINE_LOG)
140  if (ha_flush_logs(NULL))
141  result= 1;
142 
143  if (options & REFRESH_BINARY_LOG)
144  {
145  /*
146  Writing this command to the binlog may result in infinite loops
147  when doing mysqlbinlog|mysql, and anyway it does not really make
148  sense to log it automatically (would cause more trouble to users
149  than it would help them)
150  */
151  tmp_write_to_binlog= 0;
152  if (mysql_bin_log.is_open())
153  {
154  if (mysql_bin_log.rotate_and_purge(true))
155  *write_to_binlog= -1;
156  }
157  }
158  if (options & REFRESH_RELAY_LOG)
159  {
160 #ifdef HAVE_REPLICATION
161  mysql_mutex_lock(&LOCK_active_mi);
162  if (active_mi != NULL)
163  {
164  mysql_mutex_lock(&active_mi->data_lock);
165  if (rotate_relay_log(active_mi))
166  *write_to_binlog= -1;
167  mysql_mutex_unlock(&active_mi->data_lock);
168  }
169  mysql_mutex_unlock(&LOCK_active_mi);
170 #endif
171  }
172 #ifdef HAVE_QUERY_CACHE
173  if (options & REFRESH_QUERY_CACHE_FREE)
174  {
175  query_cache.pack(); // FLUSH QUERY CACHE
176  options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory
177  }
178  if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
179  {
180  query_cache.flush(); // RESET QUERY CACHE
181  }
182 #endif /*HAVE_QUERY_CACHE*/
183 
184  DBUG_ASSERT(!thd || thd->locked_tables_mode ||
185  !thd->mdl_context.has_locks() ||
186  thd->handler_tables_hash.records ||
187  thd->global_read_lock.is_acquired());
188 
189  /*
190  Note that if REFRESH_READ_LOCK bit is set then REFRESH_TABLES is set too
191  (see sql_yacc.yy)
192  */
193  if (options & (REFRESH_TABLES | REFRESH_READ_LOCK))
194  {
195  if ((options & REFRESH_READ_LOCK) && thd)
196  {
197  /*
198  On the first hand we need write lock on the tables to be flushed,
199  on the other hand we must not try to aspire a global read lock
200  if we have a write locked table as this would lead to a deadlock
201  when trying to reopen (and re-lock) the table after the flush.
202  */
203  if (thd->locked_tables_mode)
204  {
205  my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
206  return 1;
207  }
208  /*
209  Writing to the binlog could cause deadlocks, as we don't log
210  UNLOCK TABLES
211  */
212  tmp_write_to_binlog= 0;
213  if (thd->global_read_lock.lock_global_read_lock(thd))
214  return 1; // Killed
215  if (close_cached_tables(thd, tables,
216  ((options & REFRESH_FAST) ? FALSE : TRUE),
217  thd->variables.lock_wait_timeout))
218  {
219  /*
220  NOTE: my_error() has been already called by reopen_tables() within
221  close_cached_tables().
222  */
223  result= 1;
224  }
225 
226  if (thd->global_read_lock.make_global_read_lock_block_commit(thd)) // Killed
227  {
228  /* Don't leave things in a half-locked state */
229  thd->global_read_lock.unlock_global_read_lock(thd);
230  return 1;
231  }
232  }
233  else
234  {
235  if (thd && thd->locked_tables_mode)
236  {
237  /*
238  If we are under LOCK TABLES we should have a write
239  lock on tables which we are going to flush.
240  */
241  if (tables)
242  {
243  for (TABLE_LIST *t= tables; t; t= t->next_local)
244  if (!find_table_for_mdl_upgrade(thd, t->db, t->table_name, false))
245  return 1;
246  }
247  else
248  {
249  /*
250  It is not safe to upgrade the metadata lock without GLOBAL IX lock.
251  This can happen with FLUSH TABLES <list> WITH READ LOCK as we in these
252  cases don't take a GLOBAL IX lock in order to be compatible with
253  global read lock.
254  */
255  if (thd->open_tables &&
256  !thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "",
257  MDL_INTENTION_EXCLUSIVE))
258  {
259  my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),
260  thd->open_tables->s->table_name.str);
261  return true;
262  }
263 
264  for (TABLE *tab= thd->open_tables; tab; tab= tab->next)
265  {
266  if (! tab->mdl_ticket->is_upgradable_or_exclusive())
267  {
268  my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),
269  tab->s->table_name.str);
270  return 1;
271  }
272  }
273  }
274  }
275 
276  if (close_cached_tables(thd, tables,
277  ((options & REFRESH_FAST) ? FALSE : TRUE),
278  (thd ? thd->variables.lock_wait_timeout :
279  LONG_TIMEOUT)))
280  {
281  /*
282  NOTE: my_error() has been already called by reopen_tables() within
283  close_cached_tables().
284  */
285  result= 1;
286  }
287  }
288  my_dbopt_cleanup();
289  }
290  if (options & REFRESH_HOSTS)
291  hostname_cache_refresh();
292  if (thd && (options & REFRESH_STATUS))
293  refresh_status(thd);
294  if (options & REFRESH_THREADS)
295  kill_blocked_pthreads();
296 #ifdef HAVE_REPLICATION
297  if (options & REFRESH_MASTER)
298  {
299  DBUG_ASSERT(thd);
300  tmp_write_to_binlog= 0;
301  if (reset_master(thd))
302  {
303  /* NOTE: my_error() has been already called by reset_master(). */
304  result= 1;
305  }
306  }
307 #endif
308 #ifdef OPENSSL
309  if (options & REFRESH_DES_KEY_FILE)
310  {
311  if (des_key_file && load_des_key_file(des_key_file))
312  {
313  /* NOTE: my_error() has been already called by load_des_key_file(). */
314  result= 1;
315  }
316  }
317 #endif
318 #ifdef HAVE_REPLICATION
319  if (options & REFRESH_SLAVE)
320  {
321  tmp_write_to_binlog= 0;
322  mysql_mutex_lock(&LOCK_active_mi);
323  if (active_mi != NULL && reset_slave(thd, active_mi))
324  {
325  /* NOTE: my_error() has been already called by reset_slave(). */
326  result= 1;
327  }
328  else if (active_mi == NULL)
329  {
330  result= 1;
331  my_error(ER_SLAVE_CONFIGURATION, MYF(0));
332  }
333  mysql_mutex_unlock(&LOCK_active_mi);
334  }
335 #endif
336  if (options & REFRESH_USER_RESOURCES)
337  reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
338  if (*write_to_binlog != -1)
339  *write_to_binlog= tmp_write_to_binlog;
340  /*
341  If the query was killed then this function must fail.
342  */
343  return result || (thd ? thd->killed : 0);
344 }
345 
346 
421 bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
422 {
423  Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
424  TABLE_LIST *table_list;
425 
426  /*
427  This is called from SQLCOM_FLUSH, the transaction has
428  been committed implicitly.
429  */
430 
431  if (thd->locked_tables_mode)
432  {
433  my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
434  goto error;
435  }
436 
437  /*
438  Acquire SNW locks on tables to be flushed. Don't acquire global
439  IX and database-scope IX locks on the tables as this will make
440  this statement incompatible with FLUSH TABLES WITH READ LOCK.
441  */
442  if (lock_table_names(thd, all_tables, NULL,
443  thd->variables.lock_wait_timeout,
444  MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK))
445  goto error;
446 
447  DEBUG_SYNC(thd,"flush_tables_with_read_lock_after_acquire_locks");
448 
449  for (table_list= all_tables; table_list;
450  table_list= table_list->next_global)
451  {
452  /* Request removal of table from cache. */
453  tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
454  table_list->db,
455  table_list->table_name, FALSE);
456  /* Reset ticket to satisfy asserts in open_tables(). */
457  table_list->mdl_request.ticket= NULL;
458  }
459 
460  /*
461  Before opening and locking tables the below call also waits
462  for old shares to go away, so the fact that we don't pass
463  MYSQL_OPEN_IGNORE_FLUSH flag to it is important.
464  Also we don't pass MYSQL_OPEN_HAS_MDL_LOCK flag as we want
465  to open underlying tables if merge table is flushed.
466  For underlying tables of the merge the below call has to
467  acquire SNW locks to ensure that they can be locked for
468  read without further waiting.
469  */
470  if (open_and_lock_tables(thd, all_tables, FALSE,
471  MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK,
472  &lock_tables_prelocking_strategy) ||
473  thd->locked_tables_list.init_locked_tables(thd))
474  {
475  goto error;
476  }
477  thd->variables.option_bits|= OPTION_TABLE_LOCK;
478 
479  /*
480  We don't downgrade MDL_SHARED_NO_WRITE here as the intended
481  post effect of this call is identical to LOCK TABLES <...> READ,
482  and we didn't use thd->in_lock_talbes and
483  thd->sql_command= SQLCOM_LOCK_TABLES hacks to enter the LTM.
484  */
485 
486  return FALSE;
487 
488 error:
489  return TRUE;
490 }
491 
492 
511 bool flush_tables_for_export(THD *thd, TABLE_LIST *all_tables)
512 {
513  Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
514 
515  /*
516  This is called from SQLCOM_FLUSH, the transaction has
517  been committed implicitly.
518  */
519 
520  if (thd->locked_tables_mode)
521  {
522  my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
523  return true;
524  }
525 
526  /*
527  Acquire SNW locks on tables to be exported. Don't acquire
528  global IX as this will make this statement incompatible
529  with FLUSH TABLES WITH READ LOCK.
530  */
531  if (open_and_lock_tables(thd, all_tables, false,
532  MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK,
533  &lock_tables_prelocking_strategy))
534  {
535  return true;
536  }
537 
538  // Check if all storage engines support FOR EXPORT.
539  for (TABLE_LIST *table_list= all_tables; table_list;
540  table_list= table_list->next_global)
541  {
542  if (!(table_list->table->file->ha_table_flags() & HA_CAN_EXPORT))
543  {
544  my_error(ER_ILLEGAL_HA, MYF(0), table_list->table_name);
545  return true;
546  }
547  }
548 
549  // Notify the storage engines that the tables should be made ready for export.
550  for (TABLE_LIST *table_list= all_tables; table_list;
551  table_list= table_list->next_global)
552  {
553  handler *handler_file= table_list->table->file;
554  int error= handler_file->extra(HA_EXTRA_EXPORT);
555  if (error)
556  {
557  handler_file->print_error(error, MYF(0));
558  return true;
559  }
560  }
561 
562  // Enter LOCKED TABLES mode.
563  if (thd->locked_tables_list.init_locked_tables(thd))
564  return true;
565  thd->variables.option_bits|= OPTION_TABLE_LOCK;
566 
567  return false;
568 }