Merge lp:~sergei.glushchenko/percona-server/5.5-ST39577-ps-bug1070255 into lp:percona-server/5.5

Proposed by Sergei Glushchenko on 2014-03-17
Status: Merged
Approved by: Laurynas Biveinis on 2014-03-18
Approved revision: 625
Merged at revision: 642
Proposed branch: lp:~sergei.glushchenko/percona-server/5.5-ST39577-ps-bug1070255
Merge into: lp:percona-server/5.5
Diff against target: 1046 lines (+280/-152)
17 files modified
mysql-test/suite/rpl/r/rpl_percona_bug1070255.result (+35/-0)
mysql-test/suite/rpl/t/rpl_percona_bug1070255.test (+51/-0)
mysys/mf_iocache2.c (+14/-1)
sql/log.cc (+3/-3)
sql/log_event.cc (+39/-60)
sql/log_event.h (+12/-10)
sql/log_event_old.cc (+15/-24)
sql/log_event_old.h (+2/-2)
sql/rpl_tblmap.cc (+11/-11)
sql/rpl_tblmap.h (+6/-6)
sql/sql_base.cc (+10/-15)
sql/sql_class.cc (+1/-1)
sql/table.cc (+2/-2)
sql/table.h (+9/-8)
sql/table_id.h (+61/-0)
storage/myisammrg/ha_myisammrg.cc (+4/-4)
storage/myisammrg/ha_myisammrg.h (+5/-5)
To merge this branch: bzr merge lp:~sergei.glushchenko/percona-server/5.5-ST39577-ps-bug1070255
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) 2014-03-17 Approve on 2014-03-18
Review via email: mp+211282@code.launchpad.net

Description of the change

To post a comment you must log in.
625. By Sergei Glushchenko on 2014-03-17

Bug 1070255: overflow caused replication sql thread failed to execute events
Straightforward backport from MySQL 5.6

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'mysql-test/suite/rpl/r/rpl_percona_bug1070255.result'
2--- mysql-test/suite/rpl/r/rpl_percona_bug1070255.result 1970-01-01 00:00:00 +0000
3+++ mysql-test/suite/rpl/r/rpl_percona_bug1070255.result 2014-03-17 10:54:24 +0000
4@@ -0,0 +1,35 @@
5+include/master-slave.inc
6+[connection master]
7+set global DEBUG='+d,dbug_table_map_id_500';
8+CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(20));
9+INSERT INTO t2 VALUES(1, '1');
10+set global DEBUG='+d,dbug_table_map_id_4B_UINT_MAX+501';
11+CREATE TABLE t3 (a INT PRIMARY KEY, b VARCHAR(20));
12+INSERT INTO t3 VALUES(1, '1');
13+set global DEBUG='+d,dbug_table_map_id_6B_UINT_MAX';
14+CREATE TABLE t4 (a INT PRIMARY KEY, b VARCHAR(20));
15+INSERT INTO t4 VALUES(1, '1');
16+UPDATE t2, t3, t4 SET t2.b='tt2', t3.b='tt3', t4.b='tt4' WHERE t2.a=t3.a and t2.a=t4.a;
17+SELECT * FROM t2;
18+a b
19+1 tt2
20+SELECT * FROM t3;
21+a b
22+1 tt3
23+SELECT * FROM t4;
24+a b
25+1 tt4
26+DELETE FROM t2;
27+DELETE FROM t3;
28+DELETE FROM t4;
29+SELECT * FROM t2;
30+a b
31+SELECT * FROM t3;
32+a b
33+SELECT * FROM t4;
34+a b
35+DROP TABLE t2;
36+DROP TABLE t3;
37+DROP TABLE t4;
38+set global DEBUG='';
39+include/rpl_end.inc
40
41=== added file 'mysql-test/suite/rpl/t/rpl_percona_bug1070255.test'
42--- mysql-test/suite/rpl/t/rpl_percona_bug1070255.test 1970-01-01 00:00:00 +0000
43+++ mysql-test/suite/rpl/t/rpl_percona_bug1070255.test 2014-03-17 10:54:24 +0000
44@@ -0,0 +1,51 @@
45+#
46+# Bug 1070255: overflow caused replication sql thread failed to execute events
47+#
48+
49+source include/have_debug.inc;
50+source include/have_binlog_format_row.inc;
51+source include/master-slave.inc;
52+
53+connection master;
54+
55+set global DEBUG='+d,dbug_table_map_id_500';
56+CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(20));
57+INSERT INTO t2 VALUES(1, '1');
58+
59+set global DEBUG='+d,dbug_table_map_id_4B_UINT_MAX+501';
60+CREATE TABLE t3 (a INT PRIMARY KEY, b VARCHAR(20));
61+INSERT INTO t3 VALUES(1, '1');
62+
63+set global DEBUG='+d,dbug_table_map_id_6B_UINT_MAX';
64+CREATE TABLE t4 (a INT PRIMARY KEY, b VARCHAR(20));
65+INSERT INTO t4 VALUES(1, '1');
66+
67+UPDATE t2, t3, t4 SET t2.b='tt2', t3.b='tt3', t4.b='tt4' WHERE t2.a=t3.a and t2.a=t4.a;
68+
69+sync_slave_with_master;
70+
71+SELECT * FROM t2;
72+SELECT * FROM t3;
73+SELECT * FROM t4;
74+
75+connection master;
76+
77+DELETE FROM t2;
78+DELETE FROM t3;
79+DELETE FROM t4;
80+
81+sync_slave_with_master;
82+
83+SELECT * FROM t2;
84+SELECT * FROM t3;
85+SELECT * FROM t4;
86+
87+connection master;
88+
89+DROP TABLE t2;
90+DROP TABLE t3;
91+DROP TABLE t4;
92+
93+set global DEBUG='';
94+
95+--source include/rpl_end.inc
96
97=== modified file 'mysys/mf_iocache2.c'
98--- mysys/mf_iocache2.c 2013-12-16 08:19:34 +0000
99+++ mysys/mf_iocache2.c 2014-03-17 10:54:24 +0000
100@@ -292,7 +292,7 @@
101
102
103 /*
104- Simple printf version. Supports '%s', '%d', '%u', "%ld" and "%lu"
105+ Simple printf version. Supports '%s', '%d', '%u', "%ld", "%lu" and "%llu"
106 Used for logging in MySQL
107 returns number of written character, or (size_t) -1 on error
108 */
109@@ -465,6 +465,19 @@
110 if (my_b_write(info, (uchar*) buff, length2))
111 goto err;
112 }
113+ else if (fmt[0] == 'l' && fmt[1] == 'l' && fmt[2] == 'u')
114+ {
115+ ulonglong iarg;
116+ size_t length2;
117+ char buff[32];
118+
119+ iarg = va_arg(args, ulonglong);
120+ length2= (size_t) (longlong10_to_str(iarg, buff, 10) - buff);
121+ out_length+= length2;
122+ fmt+= 2;
123+ if (my_b_write(info, (uchar *) buff, length2))
124+ goto err;
125+ }
126 else
127 {
128 /* %% or unknown code */
129
130=== modified file 'sql/log.cc'
131--- sql/log.cc 2014-03-17 07:04:40 +0000
132+++ sql/log.cc 2014-03-17 10:54:24 +0000
133@@ -5029,13 +5029,13 @@
134 {
135 int error;
136 DBUG_ENTER("THD::binlog_write_table_map");
137- DBUG_PRINT("enter", ("table: 0x%lx (%s: #%lu)",
138+ DBUG_PRINT("enter", ("table: 0x%lx (%s: #%llu)",
139 (long) table, table->s->table_name.str,
140- table->s->table_map_id));
141+ table->s->table_map_id.id()));
142
143 /* Pre-conditions */
144 DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open());
145- DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
146+ DBUG_ASSERT(table->s->table_map_id.is_valid());
147
148 Table_map_log_event
149 the_event(this, table, table->s->table_map_id, is_transactional);
150
151=== modified file 'sql/log_event.cc'
152--- sql/log_event.cc 2014-02-24 06:30:46 +0000
153+++ sql/log_event.cc 2014-03-17 10:54:24 +0000
154@@ -2025,7 +2025,7 @@
155 if (!(map= print_event_info->m_table_map.get_table(m_table_id)) ||
156 !(td= map->create_table_def()))
157 {
158- my_b_printf(file, "### Row event for unknown table #%d", m_table_id);
159+ my_b_printf(file, "### Row event for unknown table #%llu", m_table_id.id());
160 return;
161 }
162
163@@ -7588,7 +7588,8 @@
164 **************************************************************************/
165
166 #ifndef MYSQL_CLIENT
167-Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid,
168+Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg,
169+ const Table_id& tid,
170 MY_BITMAP const *cols, bool is_transactional)
171 : Log_event(thd_arg, 0, is_transactional),
172 m_row_count(0),
173@@ -7600,14 +7601,7 @@
174 , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL)
175 #endif
176 {
177- /*
178- We allow a special form of dummy event when the table, and cols
179- are null and the table id is ~0UL. This is a temporary
180- solution, to be able to terminate a started statement in the
181- binary log: the extraneous events will be removed in the future.
182- */
183- DBUG_ASSERT((tbl_arg && tbl_arg->s && tid != ~0UL) ||
184- (!tbl_arg && !cols && tid == ~0UL));
185+ DBUG_ASSERT(tbl_arg && tbl_arg->s && tid.is_valid());
186
187 if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS)
188 set_flags(NO_FOREIGN_KEY_CHECKS_F);
189@@ -7667,7 +7661,7 @@
190 }
191 else
192 {
193- m_table_id= (ulong) uint6korr(post_start);
194+ m_table_id= uint6korr(post_start);
195 post_start+= RW_FLAGS_OFFSET;
196 }
197
198@@ -7729,8 +7723,8 @@
199 const uchar* const ptr_rows_data= (const uchar*) ptr_after_width;
200
201 size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf);
202- DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu",
203- m_table_id, m_flags, m_width, (ulong) data_size));
204+ DBUG_PRINT("info",("m_table_id: %llu m_flags: %d m_width: %lu data_size: %lu",
205+ m_table_id.id(), m_flags, m_width, (ulong) data_size));
206
207 m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME));
208 if (likely((bool)m_rows_buf))
209@@ -7843,25 +7837,6 @@
210 DBUG_ENTER("Rows_log_event::do_apply_event(Relay_log_info*)");
211 int error= 0;
212 /*
213- If m_table_id == ~0UL, then we have a dummy event that does not
214- contain any data. In that case, we just remove all tables in the
215- tables_to_lock list, close the thread tables, and return with
216- success.
217- */
218- if (m_table_id == ~0UL)
219- {
220- /*
221- This one is supposed to be set: just an extra check so that
222- nothing strange has happened.
223- */
224- DBUG_ASSERT(get_flags(STMT_END_F));
225-
226- const_cast<Relay_log_info*>(rli)->slave_close_thread_tables(thd);
227- thd->clear_error();
228- DBUG_RETURN(0);
229- }
230-
231- /*
232 'thd' has been set by exec_relay_log_event(), just before calling
233 do_apply_event(). We still check here to prevent future coding
234 errors.
235@@ -8018,7 +7993,8 @@
236 table=
237 m_table= const_cast<Relay_log_info*>(rli)->m_table_map.get_table(m_table_id);
238
239- DBUG_PRINT("debug", ("m_table: 0x%lx, m_table_id: %lu", (ulong) m_table, m_table_id));
240+ DBUG_PRINT("debug", ("m_table: 0x%lx, m_table_id: %llu", (ulong) m_table,
241+ m_table_id.id()));
242
243 if (table)
244 {
245@@ -8344,14 +8320,14 @@
246 bool Rows_log_event::write_data_header(IO_CACHE *file)
247 {
248 uchar buf[ROWS_HEADER_LEN]; // No need to init the buffer
249- DBUG_ASSERT(m_table_id != ~0UL);
250+ DBUG_ASSERT(m_table_id.is_valid());
251 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
252 {
253- int4store(buf + 0, m_table_id);
254+ int4store(buf + 0, (ulong)m_table_id.id());
255 int2store(buf + 4, m_flags);
256 return (my_b_safe_write(file, buf, 6));
257 });
258- int6store(buf + RW_MAPID_OFFSET, (ulonglong)m_table_id);
259+ int6store(buf + RW_MAPID_OFFSET, m_table_id.id());
260 int2store(buf + RW_FLAGS_OFFSET, m_flags);
261 return (my_b_safe_write(file, buf, ROWS_HEADER_LEN));
262 }
263@@ -8399,7 +8375,7 @@
264 char const *const flagstr=
265 get_flags(STMT_END_F) ? " flags: STMT_END_F" : "";
266 size_t bytes= my_snprintf(buf, sizeof(buf),
267- "table_id: %lu%s", m_table_id, flagstr);
268+ "table_id: %llu%s", m_table_id.id(), flagstr);
269 protocol->store(buf, bytes, &my_charset_bin);
270 }
271 #endif
272@@ -8415,8 +8391,8 @@
273 {
274 bool const last_stmt_event= get_flags(STMT_END_F);
275 print_header(head, print_event_info, !last_stmt_event);
276- my_b_printf(head, "\t%s: table id %lu%s\n",
277- name, m_table_id,
278+ my_b_printf(head, "\t%s: table id %llu%s\n",
279+ name, m_table_id.id(),
280 last_stmt_event ? " flags: STMT_END_F" : "");
281 print_base64(body, print_event_info, !last_stmt_event);
282 }
283@@ -8509,7 +8485,8 @@
284 (tbl->s->db etc) and not pointer content.
285 */
286 #if !defined(MYSQL_CLIENT)
287-Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
288+Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl,
289+ const Table_id& tid,
290 bool is_transactional)
291 : Log_event(thd, 0, is_transactional),
292 m_table(tbl),
293@@ -8529,7 +8506,7 @@
294 {
295 uchar cbuf[sizeof(m_colcnt) + 1];
296 uchar *cbuf_end;
297- DBUG_ASSERT(m_table_id != ~0UL);
298+ DBUG_ASSERT(m_table_id.is_valid());
299 /*
300 In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in
301 table.cc / alloc_table_share():
302@@ -8610,7 +8587,7 @@
303 #endif
304 m_dbnam(NULL), m_dblen(0), m_tblnam(NULL), m_tbllen(0),
305 m_colcnt(0), m_coltype(0),
306- m_memory(NULL), m_table_id(ULONG_MAX), m_flags(0),
307+ m_memory(NULL), m_table_id(ULONGLONG_MAX), m_flags(0),
308 m_data_size(0), m_field_metadata(0), m_field_metadata_size(0),
309 m_null_bits(0), m_meta_memory(NULL)
310 {
311@@ -8643,12 +8620,10 @@
312 else
313 {
314 DBUG_ASSERT(post_header_len == TABLE_MAP_HEADER_LEN);
315- m_table_id= (ulong) uint6korr(post_start);
316+ m_table_id= uint6korr(post_start);
317 post_start+= TM_FLAGS_OFFSET;
318 }
319
320- DBUG_ASSERT(m_table_id != ~0UL);
321-
322 m_flags= uint2korr(post_start);
323
324 /* Read the variable part of the event */
325@@ -8945,10 +8920,13 @@
326 tname_mem, strlen(tname_mem),
327 tname_mem, TL_WRITE);
328
329- table_list->table_id= DBUG_EVALUATE_IF("inject_tblmap_same_id_maps_diff_table", 0, m_table_id);
330+ table_list->table_id=
331+ DBUG_EVALUATE_IF("inject_tblmap_same_id_maps_diff_table", 0, m_table_id.id());
332 table_list->updating= 1;
333 table_list->required_type= FRMTYPE_TABLE;
334- DBUG_PRINT("debug", ("table: %s is mapped to %u", table_list->table_name, table_list->table_id));
335+ DBUG_PRINT("debug", ("table: %s is mapped to %llu", table_list->table_name,
336+ table_list->table_id.id()));
337+
338 enum_tbl_map_status tblmap_status= check_table_map(rli, table_list);
339 if (tblmap_status == OK_TO_PROCESS)
340 {
341@@ -9002,9 +8980,9 @@
342 char buf[256];
343
344 my_snprintf(buf, sizeof(buf),
345- "Found table map event mapping table id %u which "
346+ "Found table map event mapping table id %llu which "
347 "was already mapped but with different settings.",
348- table_list->table_id);
349+ table_list->table_id.id());
350
351 if (thd->slave_thread)
352 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
353@@ -9045,15 +9023,15 @@
354 #ifndef MYSQL_CLIENT
355 bool Table_map_log_event::write_data_header(IO_CACHE *file)
356 {
357- DBUG_ASSERT(m_table_id != ~0UL);
358+ DBUG_ASSERT(m_table_id.is_valid());
359 uchar buf[TABLE_MAP_HEADER_LEN];
360 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
361 {
362- int4store(buf + 0, m_table_id);
363+ int4store(buf + 0, m_table_id.id());
364 int2store(buf + 4, m_flags);
365 return (my_b_safe_write(file, buf, 6));
366 });
367- int6store(buf + TM_MAPID_OFFSET, (ulonglong)m_table_id);
368+ int6store(buf + TM_MAPID_OFFSET, m_table_id.id());
369 int2store(buf + TM_FLAGS_OFFSET, m_flags);
370 return (my_b_safe_write(file, buf, TABLE_MAP_HEADER_LEN));
371 }
372@@ -9103,8 +9081,8 @@
373 {
374 char buf[256];
375 size_t bytes= my_snprintf(buf, sizeof(buf),
376- "table_id: %lu (%s.%s)",
377- m_table_id, m_dbnam, m_tblnam);
378+ "table_id: %llu (%s.%s)",
379+ m_table_id.id(), m_dbnam, m_tblnam);
380 protocol->store(buf, bytes, &my_charset_bin);
381 }
382 #endif
383@@ -9132,8 +9110,8 @@
384 m_tblnam,
385 strlen(m_tblnam));
386 my_b_printf(&print_event_info->head_cache,
387- "\tTable_map: %s.%s mapped to number %lu\n",
388- db_nam.c_ptr(), tbl_nam.c_ptr(), m_table_id);
389+ "\tTable_map: %s.%s mapped to number %llu\n",
390+ db_nam.c_ptr(), tbl_nam.c_ptr(), m_table_id.id());
391 print_base64(&print_event_info->body_cache, print_event_info, TRUE);
392 }
393 }
394@@ -9148,7 +9126,7 @@
395 */
396 #if !defined(MYSQL_CLIENT)
397 Write_rows_log_event::Write_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
398- ulong tid_arg,
399+ const Table_id& tid_arg,
400 MY_BITMAP const *cols,
401 bool is_transactional)
402 : Rows_log_event(thd_arg, tbl_arg, tid_arg, cols, is_transactional)
403@@ -10097,7 +10075,8 @@
404
405 #ifndef MYSQL_CLIENT
406 Delete_rows_log_event::Delete_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
407- ulong tid, MY_BITMAP const *cols,
408+ const Table_id& tid,
409+ MY_BITMAP const *cols,
410 bool is_transactional)
411 : Rows_log_event(thd_arg, tbl_arg, tid, cols, is_transactional)
412 {
413@@ -10193,7 +10172,7 @@
414 */
415 #if !defined(MYSQL_CLIENT)
416 Update_rows_log_event::Update_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
417- ulong tid,
418+ const Table_id& tid,
419 MY_BITMAP const *cols_bi,
420 MY_BITMAP const *cols_ai,
421 bool is_transactional)
422@@ -10203,7 +10182,7 @@
423 }
424
425 Update_rows_log_event::Update_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
426- ulong tid,
427+ const Table_id& tid,
428 MY_BITMAP const *cols,
429 bool is_transactional)
430 : Rows_log_event(thd_arg, tbl_arg, tid, cols, is_transactional)
431
432=== modified file 'sql/log_event.h'
433--- sql/log_event.h 2014-02-24 06:30:46 +0000
434+++ sql/log_event.h 2014-03-17 10:54:24 +0000
435@@ -34,6 +34,7 @@
436
437 #include <my_bitmap.h>
438 #include "rpl_constants.h"
439+#include "table_id.h"
440
441 #ifdef MYSQL_CLIENT
442 #include "sql_const.h"
443@@ -3485,7 +3486,8 @@
444 flag_set get_flags(flag_set flag) const { return m_flags & flag; }
445
446 #ifdef MYSQL_SERVER
447- Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, bool is_transactional);
448+ Table_map_log_event(THD *thd, TABLE *tbl, const Table_id& tid,
449+ bool is_transactional);
450 #endif
451 #ifdef HAVE_REPLICATION
452 Table_map_log_event(const char *buf, uint event_len,
453@@ -3501,7 +3503,7 @@
454 m_field_metadata_size, m_null_bits, m_flags);
455 }
456 #endif
457- ulong get_table_id() const { return m_table_id; }
458+ const Table_id& get_table_id() const { return m_table_id; }
459 const char *get_table_name() const { return m_tblnam; }
460 const char *get_db_name() const { return m_dbnam; }
461 #ifdef MYSQL_CLIENT
462@@ -3546,7 +3548,7 @@
463 uchar *m_coltype;
464
465 uchar *m_memory;
466- ulong m_table_id;
467+ Table_id m_table_id;
468 flag_set m_flags;
469
470 size_t m_data_size;
471@@ -3658,7 +3660,7 @@
472
473 MY_BITMAP const *get_cols() const { return &m_cols; }
474 size_t get_width() const { return m_width; }
475- ulong get_table_id() const { return m_table_id; }
476+ const Table_id& get_table_id() const { return m_table_id; }
477
478 #ifdef MYSQL_SERVER
479 virtual bool write_data_header(IO_CACHE *file);
480@@ -3684,7 +3686,7 @@
481 this class, not create instances of this class.
482 */
483 #ifdef MYSQL_SERVER
484- Rows_log_event(THD*, TABLE*, ulong table_id,
485+ Rows_log_event(THD*, TABLE*, const Table_id& table_id,
486 MY_BITMAP const *cols, bool is_transactional);
487 #endif
488 Rows_log_event(const char *row_data, uint event_len,
489@@ -3702,7 +3704,7 @@
490 #ifdef MYSQL_SERVER
491 TABLE *m_table; /* The table the rows belong to */
492 #endif
493- ulong m_table_id; /* Table ID */
494+ Table_id m_table_id; /* Table ID */
495 MY_BITMAP m_cols; /* Bitmap denoting columns available */
496 ulong m_width; /* The width of the columns bitmap */
497 /*
498@@ -3828,7 +3830,7 @@
499 };
500
501 #if defined(MYSQL_SERVER)
502- Write_rows_log_event(THD*, TABLE*, ulong table_id,
503+ Write_rows_log_event(THD*, TABLE*, const Table_id& table_id,
504 MY_BITMAP const *cols, bool is_transactional);
505 #endif
506 #ifdef HAVE_REPLICATION
507@@ -3886,12 +3888,12 @@
508 };
509
510 #ifdef MYSQL_SERVER
511- Update_rows_log_event(THD*, TABLE*, ulong table_id,
512+ Update_rows_log_event(THD*, TABLE*, const Table_id& table_id,
513 MY_BITMAP const *cols_bi,
514 MY_BITMAP const *cols_ai,
515 bool is_transactional);
516
517- Update_rows_log_event(THD*, TABLE*, ulong table_id,
518+ Update_rows_log_event(THD*, TABLE*, const Table_id& table_id,
519 MY_BITMAP const *cols,
520 bool is_transactional);
521
522@@ -3967,7 +3969,7 @@
523 };
524
525 #ifdef MYSQL_SERVER
526- Delete_rows_log_event(THD*, TABLE*, ulong,
527+ Delete_rows_log_event(THD*, TABLE*, const Table_id&,
528 MY_BITMAP const *cols, bool is_transactional);
529 #endif
530 #ifdef HAVE_REPLICATION
531
532=== modified file 'sql/log_event_old.cc'
533--- sql/log_event_old.cc 2013-10-22 13:33:14 +0000
534+++ sql/log_event_old.cc 2014-03-17 10:54:24 +0000
535@@ -44,12 +44,14 @@
536 uchar const *row_start= ev->m_rows_buf;
537
538 /*
539- If m_table_id == ~0UL, then we have a dummy event that does not
540- contain any data. In that case, we just remove all tables in the
541+ If m_table_id == ~0U or max 6 Bytes integer, then we have a dummy event that
542+ does not contain any data. In that case, we just remove all tables in the
543 tables_to_lock list, close the thread tables, and return with
544 success.
545 */
546- if (ev->m_table_id == ~0UL)
547+ if ((ev->m_table_id.id() == ~0U || ev->m_table_id.id() == (~0ULL >> 16)) &&
548+ ev->m_cols.n_bits == 1 && ev->m_cols.bitmap[0] == 0)
549+
550 {
551 /*
552 This one is supposed to be set: just an extra check so that
553@@ -1361,8 +1363,8 @@
554
555 const uchar* const ptr_rows_data= (const uchar*) ptr_after_width;
556 size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf);
557- DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu",
558- m_table_id, m_flags, m_width, (ulong) data_size));
559+ DBUG_PRINT("info",("m_table_id: %llu m_flags: %d m_width: %lu data_size: %lu",
560+ m_table_id.id(), m_flags, m_width, (ulong) data_size));
561 DBUG_DUMP("rows_data", (uchar*) ptr_rows_data, data_size);
562
563 m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME));
564@@ -1474,12 +1476,13 @@
565 int error= 0;
566
567 /*
568- If m_table_id == ~0UL, then we have a dummy event that does not
569- contain any data. In that case, we just remove all tables in the
570+ If m_table_id == ~0U or max 6 Bytes integer, then we have a dummy event that
571+ does not contain any data. In that case, we just remove all tables in the
572 tables_to_lock list, close the thread tables, and return with
573 success.
574 */
575- if (m_table_id == ~0UL)
576+ if ((m_table_id.id() == ~0U || m_table_id.id() == (~0ULL >> 16)) &&
577+ m_cols.n_bits == 1 && m_cols.bitmap[0] == 0)
578 {
579 /*
580 This one is supposed to be set: just an extra check so that
581@@ -1891,21 +1894,9 @@
582 #ifndef MYSQL_CLIENT
583 bool Old_rows_log_event::write_data_header(IO_CACHE *file)
584 {
585- uchar buf[ROWS_HEADER_LEN]; // No need to init the buffer
586-
587 // This method should not be reached.
588 assert(0);
589-
590- DBUG_ASSERT(m_table_id != ~0UL);
591- DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
592- {
593- int4store(buf + 0, m_table_id);
594- int2store(buf + 4, m_flags);
595- return (my_b_safe_write(file, buf, 6));
596- });
597- int6store(buf + RW_MAPID_OFFSET, (ulonglong)m_table_id);
598- int2store(buf + RW_FLAGS_OFFSET, m_flags);
599- return (my_b_safe_write(file, buf, ROWS_HEADER_LEN));
600+ return TRUE;
601 }
602
603
604@@ -1947,7 +1938,7 @@
605 char const *const flagstr=
606 get_flags(STMT_END_F) ? " flags: STMT_END_F" : "";
607 size_t bytes= my_snprintf(buf, sizeof(buf),
608- "table_id: %lu%s", m_table_id, flagstr);
609+ "table_id: %llu%s", m_table_id.id(), flagstr);
610 protocol->store(buf, bytes, &my_charset_bin);
611 }
612 #endif
613@@ -1964,8 +1955,8 @@
614 {
615 bool const last_stmt_event= get_flags(STMT_END_F);
616 print_header(head, print_event_info, !last_stmt_event);
617- my_b_printf(head, "\t%s: table id %lu%s\n",
618- name, m_table_id,
619+ my_b_printf(head, "\t%s: table id %llu%s\n",
620+ name, m_table_id.id(),
621 last_stmt_event ? " flags: STMT_END_F" : "");
622 print_base64(body, print_event_info, !last_stmt_event);
623 }
624
625=== modified file 'sql/log_event_old.h'
626--- sql/log_event_old.h 2014-02-03 04:39:37 +0000
627+++ sql/log_event_old.h 2014-03-17 10:54:24 +0000
628@@ -128,7 +128,7 @@
629
630 MY_BITMAP const *get_cols() const { return &m_cols; }
631 size_t get_width() const { return m_width; }
632- ulong get_table_id() const { return m_table_id; }
633+ const Table_id& get_table_id() const { return m_table_id; }
634
635 #ifndef MYSQL_CLIENT
636 virtual bool write_data_header(IO_CACHE *file);
637@@ -172,7 +172,7 @@
638 #ifndef MYSQL_CLIENT
639 TABLE *m_table; /* The table the rows belong to */
640 #endif
641- ulong m_table_id; /* Table ID */
642+ Table_id m_table_id; /* Table ID */
643 MY_BITMAP m_cols; /* Bitmap denoting columns available */
644 ulong m_width; /* The width of the columns bitmap */
645
646
647=== modified file 'sql/rpl_tblmap.cc'
648--- sql/rpl_tblmap.cc 2011-06-30 15:46:53 +0000
649+++ sql/rpl_tblmap.cc 2014-03-17 10:54:24 +0000
650@@ -1,4 +1,4 @@
651-/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
652+/* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
653
654 This program is free software; you can redistribute it and/or modify
655 it under the terms of the GNU General Public License as published by
656@@ -42,7 +42,7 @@
657 constructor is called at startup only.
658 */
659 (void) my_hash_init(&m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE,
660- offsetof(entry,table_id),sizeof(ulong),
661+ offsetof(entry,table_id),sizeof(ulonglong),
662 0,0,0);
663 /* We don't preallocate any block, this is consistent with m_free=0 above */
664 init_alloc_root(&m_mem_root, TABLE_ID_HASH_SIZE*sizeof(entry), 0);
665@@ -57,20 +57,20 @@
666 free_root(&m_mem_root, MYF(0));
667 }
668
669-TABLE* table_mapping::get_table(ulong table_id)
670+TABLE* table_mapping::get_table(ulonglong table_id)
671 {
672- DBUG_ENTER("table_mapping::get_table(ulong)");
673- DBUG_PRINT("enter", ("table_id: %lu", table_id));
674+ DBUG_ENTER("table_mapping::get_table(ulonglong)");
675+ DBUG_PRINT("enter", ("table_id: %llu", table_id));
676 entry *e= find_entry(table_id);
677 if (e)
678 {
679- DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)",
680+ DBUG_PRINT("info", ("tid %llu -> table 0x%lx (%s)",
681 table_id, (long) e->table,
682 MAYBE_TABLE_NAME(e->table)));
683 DBUG_RETURN(e->table);
684 }
685
686- DBUG_PRINT("info", ("tid %lu is not mapped!", table_id));
687+ DBUG_PRINT("info", ("tid %llu is not mapped!", table_id));
688 DBUG_RETURN(NULL);
689 }
690
691@@ -100,10 +100,10 @@
692 return 0;
693 }
694
695-int table_mapping::set_table(ulong table_id, TABLE* table)
696+int table_mapping::set_table(ulonglong table_id, TABLE* table)
697 {
698 DBUG_ENTER("table_mapping::set_table(ulong,TABLE*)");
699- DBUG_PRINT("enter", ("table_id: %lu table: 0x%lx (%s)",
700+ DBUG_PRINT("enter", ("table_id: %llu table: 0x%lx (%s)",
701 table_id,
702 (long) table, MAYBE_TABLE_NAME(table)));
703 entry *e= find_entry(table_id);
704@@ -131,13 +131,13 @@
705 DBUG_RETURN(ERR_MEMORY_ALLOCATION);
706 }
707
708- DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)",
709+ DBUG_PRINT("info", ("tid %llu -> table 0x%lx (%s)",
710 table_id, (long) e->table,
711 MAYBE_TABLE_NAME(e->table)));
712 DBUG_RETURN(0); // All OK
713 }
714
715-int table_mapping::remove_table(ulong table_id)
716+int table_mapping::remove_table(ulonglong table_id)
717 {
718 entry *e= find_entry(table_id);
719 if (e)
720
721=== modified file 'sql/rpl_tblmap.h'
722--- sql/rpl_tblmap.h 2013-03-19 12:36:34 +0000
723+++ sql/rpl_tblmap.h 2014-03-17 10:54:24 +0000
724@@ -1,4 +1,4 @@
725-/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
726+/* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
727
728 This program is free software; you can redistribute it and/or modify
729 it under the terms of the GNU General Public License as published by
730@@ -70,10 +70,10 @@
731 table_mapping();
732 ~table_mapping();
733
734- TABLE* get_table(ulong table_id);
735+ TABLE* get_table(ulonglong table_id);
736
737- int set_table(ulong table_id, TABLE* table);
738- int remove_table(ulong table_id);
739+ int set_table(ulonglong table_id, TABLE* table);
740+ int remove_table(ulonglong table_id);
741 void clear_tables();
742 ulong count() const { return m_table_ids.records; }
743
744@@ -83,14 +83,14 @@
745 it, which only works for PODs)
746 */
747 struct entry {
748- ulong table_id;
749+ ulonglong table_id;
750 union {
751 TABLE *table;
752 entry *next;
753 };
754 };
755
756- entry *find_entry(ulong table_id)
757+ entry *find_entry(ulonglong table_id)
758 {
759 return (entry *) my_hash_search(&m_table_ids,
760 (uchar*)&table_id,
761
762=== modified file 'sql/sql_base.cc'
763--- sql/sql_base.cc 2013-10-22 13:33:14 +0000
764+++ sql/sql_base.cc 2014-03-17 10:54:24 +0000
765@@ -3622,13 +3622,12 @@
766
767 share->table_map_id is given a value that with a high certainty is
768 not used by any other table (the only case where a table id can be
769- reused is on wrap-around, which means more than 4 billion table
770+ reused is on wrap-around, which means more than 2^48 table
771 share opens have been executed while one table was open all the
772 time).
773
774- share->table_map_id is not ~0UL.
775- */
776-static ulong last_table_id= ~0UL;
777+*/
778+static Table_id last_table_id;
779
780 void assign_new_table_id(TABLE_SHARE *share)
781 {
782@@ -3639,18 +3638,14 @@
783 DBUG_ASSERT(share != NULL);
784 mysql_mutex_assert_owner(&LOCK_open);
785
786- ulong tid= ++last_table_id; /* get next id */
787- /*
788- There is one reserved number that cannot be used. Remember to
789- change this when 6-byte global table id's are introduced.
790- */
791- if (unlikely(tid == ~0UL))
792- tid= ++last_table_id;
793- share->table_map_id= tid;
794- DBUG_PRINT("info", ("table_id=%lu", tid));
795+ DBUG_EXECUTE_IF("dbug_table_map_id_500", last_table_id= 500;);
796+ DBUG_EXECUTE_IF("dbug_table_map_id_4B_UINT_MAX+501",
797+ last_table_id= 501ULL + UINT_MAX;);
798+ DBUG_EXECUTE_IF("dbug_table_map_id_6B_UINT_MAX",
799+ last_table_id= (~0ULL >> 16););
800
801- /* Post conditions */
802- DBUG_ASSERT(share->table_map_id != ~0UL);
803+ share->table_map_id= last_table_id++;
804+ DBUG_PRINT("info", ("table_id=%llu", share->table_map_id.id()));
805
806 DBUG_VOID_RETURN;
807 }
808
809=== modified file 'sql/sql_class.cc'
810--- sql/sql_class.cc 2013-12-16 08:19:34 +0000
811+++ sql/sql_class.cc 2014-03-17 10:54:24 +0000
812@@ -4856,7 +4856,7 @@
813 {
814 DBUG_ENTER("binlog_prepare_pending_rows_event");
815 /* Pre-conditions */
816- DBUG_ASSERT(table->s->table_map_id != ~0UL);
817+ DBUG_ASSERT(table->s->table_map_id.is_valid());
818
819 /* Fetch the type code for the RowsEventT template parameter */
820 int const type_code= RowsEventT::TYPE_CODE;
821
822=== modified file 'sql/table.cc'
823--- sql/table.cc 2014-01-06 05:22:35 +0000
824+++ sql/table.cc 2014-03-17 10:54:24 +0000
825@@ -322,7 +322,7 @@
826 elsewhere, and then assign a table map id inside open_table()
827 under the protection of the LOCK_open mutex.
828 */
829- share->table_map_id= ~0UL;
830+ share->table_map_id= ~0ULL;
831 share->cached_row_logging_check= -1;
832
833 share->used_tables.empty();
834@@ -388,7 +388,7 @@
835 table_map_id is also used for MERGE tables to suppress repeated
836 compatibility checks.
837 */
838- share->table_map_id= (ulong) thd->query_id;
839+ share->table_map_id= (ulonglong) thd->query_id;
840
841 share->used_tables.empty();
842 share->free_tables.empty();
843
844=== modified file 'sql/table.h'
845--- sql/table.h 2014-02-03 04:39:37 +0000
846+++ sql/table.h 2014-03-17 10:54:24 +0000
847@@ -28,6 +28,7 @@
848 #include "handler.h" /* row_type, ha_choice, handler */
849 #include "mysql_com.h" /* enum_field_types */
850 #include "thr_lock.h" /* thr_lock_type */
851+#include "table_id.h"
852
853 /* Structs that defines the TABLE */
854
855@@ -642,7 +643,7 @@
856 bool db_low_byte_first; /* Portable row format */
857 bool crashed;
858 bool is_view;
859- ulong table_map_id; /* for row-based replication */
860+ Table_id table_map_id; /* for row-based replication */
861
862 /*
863 Cache for row-based replication table share checks that does not
864@@ -766,7 +767,7 @@
865 return (table_category == TABLE_CATEGORY_LOG);
866 }
867
868- inline ulong get_table_def_version()
869+ inline ulonglong get_table_def_version()
870 {
871 return table_map_id;
872 }
873@@ -871,9 +872,9 @@
874
875 @sa TABLE_LIST::is_table_ref_id_equal()
876 */
877- ulong get_table_ref_version() const
878+ ulonglong get_table_ref_version() const
879 {
880- return (tmp_table == SYSTEM_TMP_TABLE || is_view) ? 0 : table_map_id;
881+ return (tmp_table == SYSTEM_TMP_TABLE || is_view) ? 0 : table_map_id.id();
882 }
883
884 bool visit_subgraph(Wait_for_flush *waiting_ticket,
885@@ -1462,7 +1463,7 @@
886 /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
887 List<Index_hint> *index_hints;
888 TABLE *table; /* opened table */
889- uint table_id; /* table id (from binlog) for opened table */
890+ Table_id table_id; /* table id (from binlog) for opened table */
891 /*
892 select_result for derived table to pass it from table creation to table
893 filling procedure
894@@ -1779,7 +1780,7 @@
895
896 inline
897 void set_table_ref_id(enum_table_ref_type table_ref_type_arg,
898- ulong table_ref_version_arg)
899+ ulonglong table_ref_version_arg)
900 {
901 m_table_ref_type= table_ref_type_arg;
902 m_table_ref_version= table_ref_version_arg;
903@@ -1810,8 +1811,8 @@
904 bool prep_where(THD *thd, Item **conds, bool no_where_clause);
905 /** See comments for set_metadata_id() */
906 enum enum_table_ref_type m_table_ref_type;
907- /** See comments for set_metadata_id() */
908- ulong m_table_ref_version;
909+ /** See comments for TABLE_SHARE::get_table_ref_version() */
910+ ulonglong m_table_ref_version;
911 };
912
913 class Item;
914
915=== added file 'sql/table_id.h'
916--- sql/table_id.h 1970-01-01 00:00:00 +0000
917+++ sql/table_id.h 2014-03-17 10:54:24 +0000
918@@ -0,0 +1,61 @@
919+/* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
920+
921+ This program is free software; you can redistribute it and/or modify
922+ it under the terms of the GNU General Public License as published by
923+ the Free Software Foundation; version 2 of the License.
924+
925+ This program is distributed in the hope that it will be useful,
926+ but WITHOUT ANY WARRANTY; without even the implied warranty of
927+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
928+ GNU General Public License for more details.
929+
930+ You should have received a copy of the GNU General Public License
931+ along with this program; if not, write to the Free Software
932+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
933+
934+#ifndef TABLE_ID_INCLUDED
935+#define TABLE_ID_INCLUDED
936+
937+#include "my_global.h"
938+
939+/*
940+ Each table share has a table id, it is mainly used for row based replication.
941+ Meanwhile it is used as table's version too.
942+*/
943+class Table_id
944+{
945+private:
946+ /* In table map event and rows events, table id is 6 bytes.*/
947+ static const ulonglong TABLE_ID_MAX= (~0ULL >> 16);
948+ ulonglong m_id;
949+
950+public:
951+ Table_id() : m_id(0) {}
952+ Table_id(ulonglong id) : m_id(id) {}
953+
954+ ulonglong id() const { return m_id; }
955+ bool is_valid() const { return m_id <= TABLE_ID_MAX; }
956+ bool is_invalid() const { return m_id > TABLE_ID_MAX; }
957+
958+ void operator=(const Table_id &tid) { m_id = tid.m_id; }
959+ void operator=(ulonglong id) { m_id = id; }
960+
961+ bool operator==(const Table_id &tid) const { return m_id == tid.m_id; }
962+ bool operator!=(const Table_id &tid) const { return m_id != tid.m_id; }
963+
964+ /* Support implicit type converting from Table_id to ulonglong */
965+ operator ulonglong() const { return m_id; }
966+
967+ Table_id operator++(int)
968+ {
969+ Table_id id(m_id);
970+
971+ /* m_id is reset to 0, when it exceeds the max value. */
972+ m_id = (m_id == TABLE_ID_MAX ? 0 : m_id + 1);
973+
974+ DBUG_ASSERT(m_id <= TABLE_ID_MAX );
975+ return id;
976+ }
977+};
978+
979+#endif
980
981=== modified file 'storage/myisammrg/ha_myisammrg.cc'
982--- storage/myisammrg/ha_myisammrg.cc 2011-08-15 18:12:11 +0000
983+++ storage/myisammrg/ha_myisammrg.cc 2014-03-17 10:54:24 +0000
984@@ -1,4 +1,4 @@
985-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
986+/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
987
988 This program is free software; you can redistribute it and/or modify
989 it under the terms of the GNU General Public License as published by
990@@ -652,9 +652,9 @@
991 from a different share than last time it was used with this MERGE
992 table.
993 */
994- DBUG_PRINT("myrg", ("table_def_version last: %lu current: %lu",
995- (ulong) mrg_child_def->get_child_def_version(),
996- (ulong) child->s->get_table_def_version()));
997+ DBUG_PRINT("myrg", ("table_def_version last: %llu current: %llu",
998+ mrg_child_def->get_child_def_version(),
999+ child->s->get_table_def_version()));
1000 if (mrg_child_def->get_child_def_version() != child->s->get_table_def_version())
1001 param->need_compat_check= TRUE;
1002
1003
1004=== modified file 'storage/myisammrg/ha_myisammrg.h'
1005--- storage/myisammrg/ha_myisammrg.h 2011-07-03 23:48:19 +0000
1006+++ storage/myisammrg/ha_myisammrg.h 2014-03-17 10:54:24 +0000
1007@@ -1,5 +1,5 @@
1008 /*
1009- Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
1010+ Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
1011
1012 This program is free software; you can redistribute it and/or modify
1013 it under the terms of the GNU General Public License as published by
1014@@ -34,7 +34,7 @@
1015 {
1016 /* Remembered MERGE child def version. See top comment in ha_myisammrg.cc */
1017 enum_table_ref_type m_child_table_ref_type;
1018- ulong m_child_def_version;
1019+ ulonglong m_child_def_version;
1020 public:
1021 LEX_STRING db;
1022 LEX_STRING name;
1023@@ -44,12 +44,12 @@
1024 {
1025 return m_child_table_ref_type;
1026 }
1027- inline ulong get_child_def_version()
1028+ inline ulonglong get_child_def_version()
1029 {
1030 return m_child_def_version;
1031 }
1032 inline void set_child_def_version(enum_table_ref_type child_table_ref_type,
1033- ulong version)
1034+ ulonglong version)
1035 {
1036 m_child_table_ref_type= child_table_ref_type;
1037 m_child_def_version= version;
1038@@ -62,7 +62,7 @@
1039 db.length= db_len_arg;
1040 name.str= table_name_arg;
1041 name.length= table_name_len_arg;
1042- m_child_def_version= ~0UL;
1043+ m_child_def_version= ~0ULL;
1044 m_child_table_ref_type= TABLE_REF_NULL;
1045 }
1046 };

Subscribers

People subscribed via source and target branches