My Project
|
00001 /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; version 2 of the License. 00006 00007 This program is distributed in the hope that it will be useful, 00008 but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 GNU General Public License for more details. 00011 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software Foundation, 00014 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 00015 00016 #ifndef RPL_SLAVE_H 00017 #define RPL_SLAVE_H 00018 00019 typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL, SLAVE_THD_WORKER } SLAVE_THD_TYPE; 00020 00024 #define MASTER_DELAY_MAX (0x7FFFFFFF) 00025 #if INT_MAX < 0x7FFFFFFF 00026 #error "don't support platforms where INT_MAX < 0x7FFFFFFF" 00027 #endif 00028 00044 #define SLAVE_MAX_HEARTBEAT_PERIOD 4294967 00045 00046 #ifdef HAVE_REPLICATION 00047 00048 #include "log.h" 00049 #include "binlog.h" 00050 #include "my_list.h" 00051 #include "rpl_filter.h" 00052 #include "rpl_tblmap.h" 00053 00054 #define SLAVE_NET_TIMEOUT 3600 00055 00056 #define MAX_SLAVE_ERROR 2000 00057 00058 #define MTS_WORKER_UNDEF ((ulong) -1) 00059 #define MTS_MAX_WORKERS 1024 00060 00061 /* 00062 When using tables to store the slave workers bitmaps, 00063 we use a BLOB field. The maximum size of a BLOB is: 00064 00065 2^16-1 = 65535 bytes => (2^16-1) * 8 = 524280 bits 00066 */ 00067 #define MTS_MAX_BITS_IN_GROUP ((1L << 19) - 8) /* 524280 */ 00068 00069 // Forward declarations 00070 class Relay_log_info; 00071 class Master_info; 00072 00073 extern bool server_id_supplied; 00074 00075 /***************************************************************************** 00076 00077 MySQL Replication 00078 00079 Replication is implemented via two types of threads: 00080 00081 I/O Thread - One of these threads is started for each master server. 00082 They maintain a connection to their master server, read log 00083 events from the master as they arrive, and queues them into 00084 a single, shared relay log file. A Master_info 00085 represents each of these threads. 00086 00087 SQL Thread - One of these threads is started and reads from the relay log 00088 file, executing each event. A Relay_log_info 00089 represents this thread. 00090 00091 Buffering in the relay log file makes it unnecessary to reread events from 00092 a master server across a slave restart. It also decouples the slave from 00093 the master where long-running updates and event logging are concerned--ie 00094 it can continue to log new events while a slow query executes on the slave. 00095 00096 *****************************************************************************/ 00097 00098 /* 00099 MUTEXES in replication: 00100 00101 LOCK_active_mi: [note: this was originally meant for multimaster, to switch 00102 from a master to another, to protect active_mi] It is used to SERIALIZE ALL 00103 administrative commands of replication: START SLAVE, STOP SLAVE, CHANGE 00104 MASTER, RESET SLAVE, end_slave() (when mysqld stops) [init_slave() does not 00105 need it it's called early]. Any of these commands holds the mutex from the 00106 start till the end. This thus protects us against a handful of deadlocks 00107 (consider start_slave_thread() which, when starting the I/O thread, releases 00108 mi->run_lock, keeps rli->run_lock, and tries to re-acquire mi->run_lock). 00109 00110 Currently active_mi never moves (it's created at startup and deleted at 00111 shutdown, and not changed: it always points to the same Master_info struct), 00112 because we don't have multimaster. So for the moment, mi does not move, and 00113 mi->rli does not either. 00114 00115 In Master_info: run_lock, data_lock 00116 run_lock protects all information about the run state: slave_running, thd 00117 and the existence of the I/O thread (to stop/start it, you need this mutex). 00118 data_lock protects some moving members of the struct: counters (log name, 00119 position) and relay log (MYSQL_BIN_LOG object). 00120 00121 In Relay_log_info: run_lock, data_lock 00122 see Master_info 00123 However, note that run_lock does not protect 00124 Relay_log_info.run_state; that is protected by data_lock. 00125 00126 In MYSQL_BIN_LOG: LOCK_log, LOCK_index of the binlog and the relay log 00127 LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog 00128 (so that you have to update the .index file). 00129 00130 ==== Order of acquisition ==== 00131 00132 Here, we list most major functions that acquire multiple locks. 00133 00134 Notation: For each function, we list the locks it takes, in the 00135 order it takes them. If a function holds lock A while taking lock 00136 B, then we write "A, B". If a function locks A, unlocks A, then 00137 locks B, then we write "A | B". If function F1 invokes function F2, 00138 then we write F2's name in parentheses in the list of locks for F1. 00139 00140 show_master_info: 00141 mi.data_lock, rli.data_lock, mi.err_lock, rli.err_lock 00142 00143 stop_slave: 00144 LOCK_active_mi, 00145 ( mi.run_lock, thd.LOCK_thd_data 00146 | rli.run_lock, thd.LOCK_thd_data 00147 | relay.LOCK_log 00148 ) 00149 00150 start_slave: 00151 mi.run_lock, rli.run_lock, rli.data_lock, global_sid_lock->wrlock 00152 00153 reset_logs: 00154 LOCK_thread_count, .LOCK_log, .LOCK_index, global_sid_lock->wrlock 00155 00156 purge_relay_logs: 00157 rli.data_lock, (relay.reset_logs) LOCK_thread_count, 00158 relay.LOCK_log, relay.LOCK_index, global_sid_lock->wrlock 00159 00160 reset_master: 00161 (binlog.reset_logs) LOCK_thread_count, binlog.LOCK_log, 00162 binlog.LOCK_index, global_sid_lock->wrlock 00163 00164 reset_slave: 00165 mi.run_lock, rli.run_lock, (purge_relay_logs) rli.data_lock, 00166 LOCK_thread_count, relay.LOCK_log, relay.LOCK_index, 00167 global_sid_lock->wrlock 00168 00169 purge_logs: 00170 .LOCK_index, LOCK_thread_count, thd.linfo.lock 00171 00172 [Note: purge_logs contains a known bug: LOCK_index should not be 00173 taken before LOCK_thread_count. This implies that, e.g., 00174 purge_master_logs can deadlock with reset_master. However, 00175 although purge_first_log and reset_slave take locks in reverse 00176 order, they cannot deadlock because they both first acquire 00177 rli.data_lock.] 00178 00179 purge_master_logs, purge_master_logs_before_date, purge: 00180 (binlog.purge_logs) binlog.LOCK_index, LOCK_thread_count, thd.linfo.lock 00181 00182 purge_first_log: 00183 rli.data_lock, relay.LOCK_index, rli.log_space_lock, 00184 (relay.purge_logs) LOCK_thread_count, thd.linfo.lock 00185 00186 MYSQL_BIN_LOG::new_file_impl: 00187 .LOCK_log, .LOCK_index, 00188 ( [ if binlog: LOCK_prep_xids ] 00189 | global_sid_lock->wrlock 00190 ) 00191 00192 rotate_relay_log: 00193 (relay.new_file_impl) relay.LOCK_log, relay.LOCK_index, 00194 global_sid_lock->wrlock 00195 00196 kill_zombie_dump_threads: 00197 LOCK_thread_count, thd.LOCK_thd_data 00198 00199 init_relay_log_pos: 00200 rli.data_lock, relay.log_lock 00201 00202 rli_init_info: 00203 rli.data_lock, 00204 ( relay.log_lock 00205 | global_sid_lock->wrlock 00206 | (relay.open_binlog) 00207 | (init_relay_log_pos) rli.data_lock, relay.log_lock 00208 ) 00209 00210 change_master: 00211 mi.run_lock, rli.run_lock, (init_relay_log_pos) rli.data_lock, 00212 relay.log_lock 00213 00214 So the DAG of lock acquisition order (not counting the buggy 00215 purge_logs) is, empirically: 00216 00217 LOCK_active_mi, mi.run_lock, rli.run_lock, 00218 ( rli.data_lock, 00219 ( LOCK_thread_count, 00220 ( 00221 ( binlog.LOCK_log, binlog.LOCK_index 00222 | relay.LOCK_log, relay.LOCK_index 00223 ), 00224 ( rli.log_space_lock | global_sid_lock->wrlock ) 00225 | binlog.LOCK_log, binlog.LOCK_index, LOCK_prep_xids 00226 | thd.LOCK_data 00227 ) 00228 | mi.err_lock, rli.err_lock 00229 ) 00230 ) 00231 ) 00232 | mi.data_lock, rli.data_lock 00233 */ 00234 00235 extern ulong master_retry_count; 00236 extern MY_BITMAP slave_error_mask; 00237 extern char slave_skip_error_names[]; 00238 extern bool use_slave_mask; 00239 extern char *slave_load_tmpdir; 00240 extern char *master_info_file, *relay_log_info_file; 00241 extern char *opt_relay_logname, *opt_relaylog_index_name; 00242 extern char *opt_binlog_index_name; 00243 extern my_bool opt_skip_slave_start, opt_reckless_slave; 00244 extern my_bool opt_log_slave_updates; 00245 extern char *opt_slave_skip_errors; 00246 extern ulonglong relay_log_space_limit; 00247 00248 extern const char *relay_log_index; 00249 extern const char *relay_log_basename; 00250 00251 /* 00252 3 possible values for Master_info::slave_running and 00253 Relay_log_info::slave_running. 00254 The values 0,1,2 are very important: to keep the diff small, I didn't 00255 substitute places where we use 0/1 with the newly defined symbols. So don't change 00256 these values. 00257 The same way, code is assuming that in Relay_log_info we use only values 00258 0/1. 00259 I started with using an enum, but 00260 enum_variable=1; is not legal so would have required many line changes. 00261 */ 00262 #define MYSQL_SLAVE_NOT_RUN 0 00263 #define MYSQL_SLAVE_RUN_NOT_CONNECT 1 00264 #define MYSQL_SLAVE_RUN_CONNECT 2 00265 00266 /* 00267 If the following is set, if first gives an error, second will be 00268 tried. Otherwise, if first fails, we fail. 00269 */ 00270 #define SLAVE_FORCE_ALL 4 00271 00272 int start_slave(THD* thd, Master_info* mi, bool net_report); 00273 int stop_slave(THD* thd, Master_info* mi, bool net_report); 00274 bool change_master(THD* thd, Master_info* mi); 00275 int reset_slave(THD *thd, Master_info* mi); 00276 int init_slave(); 00277 int init_recovery(Master_info* mi, const char** errmsg); 00278 int global_init_info(Master_info* mi, bool ignore_if_no_info, int thread_mask); 00279 void end_info(Master_info* mi); 00280 int remove_info(Master_info* mi); 00281 int flush_master_info(Master_info* mi, bool force); 00282 void add_slave_skip_errors(const char* arg); 00283 void set_slave_skip_errors(char** slave_skip_errors_ptr); 00284 int register_slave_on_master(MYSQL* mysql); 00285 int terminate_slave_threads(Master_info* mi, int thread_mask, 00286 bool need_lock_term= true); 00287 int start_slave_threads(bool need_lock_slave, bool wait_for_start, 00288 Master_info* mi, int thread_mask); 00289 /* 00290 cond_lock is usually same as start_lock. It is needed for the case when 00291 start_lock is 0 which happens if start_slave_thread() is called already 00292 inside the start_lock section, but at the same time we want a 00293 mysql_cond_wait() on start_cond, start_lock 00294 */ 00295 int start_slave_thread( 00296 #ifdef HAVE_PSI_INTERFACE 00297 PSI_thread_key thread_key, 00298 #endif 00299 pthread_handler h_func, 00300 mysql_mutex_t *start_lock, 00301 mysql_mutex_t *cond_lock, 00302 mysql_cond_t *start_cond, 00303 volatile uint *slave_running, 00304 volatile ulong *slave_run_id, 00305 Master_info *mi); 00306 00307 /* retrieve table from master and copy to slave*/ 00308 int fetch_master_table(THD* thd, const char* db_name, const char* table_name, 00309 Master_info* mi, MYSQL* mysql, bool overwrite); 00310 00311 bool show_slave_status(THD* thd, Master_info* mi); 00312 bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, 00313 bool (*pred)(const void *), const void *param); 00314 bool rpl_master_erroneous_autoinc(THD* thd); 00315 00316 const char *print_slave_db_safe(const char *db); 00317 void skip_load_data_infile(NET* net); 00318 00319 void end_slave(); /* release slave threads */ 00320 void close_active_mi(); /* clean up slave threads data */ 00321 void clear_until_condition(Relay_log_info* rli); 00322 void clear_slave_error(Relay_log_info* rli); 00323 void lock_slave_threads(Master_info* mi); 00324 void unlock_slave_threads(Master_info* mi); 00325 void init_thread_mask(int* mask,Master_info* mi,bool inverse); 00326 void set_slave_thread_options(THD* thd); 00327 void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli); 00328 int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli); 00329 int rotate_relay_log(Master_info* mi); 00330 00331 pthread_handler_t handle_slave_io(void *arg); 00332 pthread_handler_t handle_slave_sql(void *arg); 00333 bool net_request_file(NET* net, const char* fname); 00334 00335 extern bool volatile abort_loop; 00336 extern Master_info *active_mi; /* active_mi for multi-master */ 00337 extern LIST master_list; 00338 extern my_bool replicate_same_server_id; 00339 00340 extern int disconnect_slave_event_count, abort_slave_event_count ; 00341 00342 /* the master variables are defaults read from my.cnf or command line */ 00343 extern uint master_port, master_connect_retry, report_port; 00344 extern char * master_user, *master_password, *master_host; 00345 extern char *master_info_file, *relay_log_info_file, *report_user; 00346 extern char *report_host, *report_password; 00347 00348 extern my_bool master_ssl; 00349 extern char *master_ssl_ca, *master_ssl_capath, *master_ssl_cert; 00350 extern char *master_ssl_cipher, *master_ssl_key; 00351 00352 int mts_recovery_groups(Relay_log_info *rli); 00353 bool mts_checkpoint_routine(Relay_log_info *rli, ulonglong period, 00354 bool force, bool need_data_lock); 00355 #endif /* HAVE_REPLICATION */ 00356 00357 /* masks for start/stop operations on io and sql slave threads */ 00358 #define SLAVE_IO 1 00359 #define SLAVE_SQL 2 00360 00364 #endif