summaryrefslogtreecommitdiff
path: root/sql/log_event.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r--sql/log_event.cc56
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);