diff options
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r-- | sql/log_event.cc | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index 62dc56e7fd2..c0fd781cede 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -768,11 +768,49 @@ int Query_log_event::write(IO_CACHE* file) int Query_log_event::write_data(IO_CACHE* file) { + char buf[QUERY_HEADER_LEN]; + if (!query) return -1; - char buf[QUERY_HEADER_LEN]; - int4store(buf + Q_THREAD_ID_OFFSET, thread_id); + /* + We want to store the thread id: + (- as an information for the user when he reads the binlog) + - if the query uses temporary table: for the slave SQL thread to know to + which master connection the temp table belongs. + Now imagine we (write_data()) are called by the slave SQL thread (we are + logging a query executed by this thread; the slave runs with + --log-slave-updates). Then this query will be logged with + thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of + the same name were created simultaneously on the master (in the master + binlog you have + CREATE TEMPORARY TABLE t; (thread 1) + CREATE TEMPORARY TABLE t; (thread 2) + ...) + then in the slave's binlog there will be + CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread) + CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread) + which is bad (same thread id!). + + To avoid this, we log the thread's thread id EXCEPT for the SQL + slave thread for which we log the original (master's) thread id. + Now this moves the bug: what happens if the thread id on the + master was 10 and when the slave replicates the query, a + connection number 10 is opened by a normal client on the slave, + and updates a temp table of the same name? We get a problem + again. To avoid this, in the handling of temp tables (sql_base.cc) + we use thread_id AND server_id. TODO when this is merged into + 4.1: in 4.1, slave_proxy_id has been renamed to pseudo_thread_id + and is a session variable: that's to make mysqlbinlog work with + temp tables. We probably need to introduce + + SET PSEUDO_SERVER_ID + for mysqlbinlog in 4.1. mysqlbinlog would print: + SET PSEUDO_SERVER_ID= + SET PSEUDO_THREAD_ID= + for each query using temp tables. + */ + int4store(buf + Q_THREAD_ID_OFFSET, slave_proxy_id); int4store(buf + Q_EXEC_TIME_OFFSET, exec_time); buf[Q_DB_LEN_OFFSET] = (char) db_len; int2store(buf + Q_ERR_CODE_OFFSET, error_code); @@ -790,12 +828,14 @@ int Query_log_event::write_data(IO_CACHE* file) #ifndef MYSQL_CLIENT Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans) - :Log_event(thd_arg, !thd_arg->tmp_table_used ? - 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans), + :Log_event(thd_arg, !thd_arg->tmp_table_used ? + 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans), data_buf(0), query(query_arg), db(thd_arg->db), q_len((uint32) query_length), - error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno), - thread_id(thd_arg->thread_id) + error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno), + thread_id(thd_arg->thread_id), + /* save the original thread id; we already know the server id */ + slave_proxy_id(thd_arg->slave_proxy_id) { time_t end_time; time(&end_time); @@ -836,7 +876,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len, return; memcpy(data_buf, buf + Q_DATA_OFFSET, data_len); - thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); + slave_proxy_id= thread_id= uint4korr(buf + Q_THREAD_ID_OFFSET); db = data_buf; db_len = (uint)buf[Q_DB_LEN_OFFSET]; query=data_buf + db_len + 1; @@ -907,8 +947,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) { thd->set_time((time_t)when); thd->query_length= q_len; - VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = (char*)query; + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->query_error= 0; // clear error @@ -1276,7 +1316,7 @@ void Load_log_event::pack_info(Protocol *protocol) int Load_log_event::write_data_header(IO_CACHE* file) { char buf[LOAD_HEADER_LEN]; - int4store(buf + L_THREAD_ID_OFFSET, thread_id); + int4store(buf + L_THREAD_ID_OFFSET, slave_proxy_id); int4store(buf + L_EXEC_TIME_OFFSET, exec_time); int4store(buf + L_SKIP_LINES_OFFSET, skip_lines); buf[L_TBL_LEN_OFFSET] = (char)table_name_len; @@ -1317,7 +1357,9 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, enum enum_duplicates handle_dup, bool using_trans) :Log_event(thd_arg, 0, using_trans), thread_id(thd_arg->thread_id), - num_fields(0), fields(0), field_lens(0),field_block_len(0), + slave_proxy_id(thd_arg->slave_proxy_id), + num_fields(0),fields(0), + field_lens(0),field_block_len(0), table_name(table_name_arg ? table_name_arg : ""), db(db_arg), fname(ex->file_name) { @@ -1422,7 +1464,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, char* buf_end = (char*)buf + event_len; uint header_len= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; const char* data_head = buf + header_len; - thread_id = uint4korr(data_head + L_THREAD_ID_OFFSET); + slave_proxy_id= thread_id= uint4korr(data_head + L_THREAD_ID_OFFSET); exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET); skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET); table_name_len = (uint)data_head[L_TBL_LEN_OFFSET]; |