diff options
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r-- | sql/log_event.cc | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index 699d1ff866d..36d2d33ade6 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -834,8 +834,11 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans) :Log_event(thd_arg, 0, 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); @@ -918,7 +921,42 @@ int Query_log_event::write_data(IO_CACHE* file) 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 ? slave_proxy_id : + thread_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); @@ -1019,7 +1057,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db) 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 ? slave_proxy_id : + thread_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; @@ -1143,10 +1182,11 @@ 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), - table_name(table_name_arg ? table_name_arg : ""), - db(db_arg), fname(ex->file_name) + 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) { time_t end_time; time(&end_time); |