Commit 3a42a50f authored by unknown's avatar unknown

Merge rkalimullin@bk-internal.mysql.com:/home/bk/mysql-5.0-maint

into  mysql.com:/home/ram/work/b29079/b29079.5.0
---
Bug #22540: Incorrect value in column End_log_pos of SHOW BINLOG EVENTS using InnoDB

fix binlog-writing so that end_log_pos is given correctly even
within transactions for both SHOW BINLOG and SHOW MASTER STATUS,
that is as absolute values (from log start) rather than relative
values (from transaction's start).
---
Merge tnurnberg@bk-internal.mysql.com:/home/bk/mysql-5.0-maint
into  sin.intern.azundris.com:/home/tnurnberg/22540/50-22540
---
Bug#22540: Incorrect value in column End_log_pos of SHOW BINLOG EVENTS using InnoDB

end_log_pos data within a transaction are relative to
the start of the transaction rather than absolute.
we fix those groups in situ before writing the log out.

additional comments and handling for groups with very
large single events, as suggested by Guilhem.
---
Merge bk-internal.mysql.com:/home/bk/mysql-5.0-maint
into  amd64.(none):/src/bug24732/my50-bug24732
---
Merge maint1.mysql.com:/data/localhome/tsmith/bk/50
into  maint1.mysql.com:/data/localhome/tsmith/bk/maint/50
---
Bug#22540: Incorrect value in column End_log_pos of SHOW BINLOG EVENTS using InnoDB
 
end_log_pos data within a transaction are relative to
the start of the transaction rather than absolute.
we fix those groups in situ before writing the log out.
 
additional comments and handling for groups with very
large single events, as suggested by Guilhem.
---
Merge tnurnberg@bk-internal.mysql.com:/home/bk/mysql-5.0-maint
into  sin.intern.azundris.com:/home/tnurnberg/22540/50-22540
---
Merge tnurnberg@bk-internal.mysql.com:/home/bk/mysql-5.1-maint
into  sin.intern.azundris.com:/home/tnurnberg/22540/51-22540
---
Merge sin.intern.azundris.com:/home/tnurnberg/22540/50-22540
into  sin.intern.azundris.com:/home/tnurnberg/22540/51-22540


mysql-test/r/rpl_truncate_7ndb.result:
  Bug #22540: Incorrect value in column End_log_pos of SHOW BINLOG EVENTS using InnoDB
  
  fix output for SHOW BINLOG EVENTS so that end_log_pos is given correctly
  even within transactions. do this by rewriting the commit-buffer in place.
  ---
  Bug#22540: Incorrect value in column End_log_pos of SHOW BINLOG EVENTS using InnoDB
  
  end_log_pos data within a transaction are relative to
  the start of the transaction rather than absolute.
  we fix those groups in situ before writing the log out.
  
  additional comments and handling for groups with very
  large single events, as suggested by Guilhem.
  ---
  Bug#22540: Incorrect value in column End_log_pos of SHOW BINLOG EVENTS using InnoDB
   
  end_log_pos data within a transaction are relative to
  the start of the transaction rather than absolute.
  we fix those groups in situ before writing the log out.
   
  additional comments and handling for groups with very
  large single events, as suggested by Guilhem.
  ---
  manual merge
sql/log.cc:
  Bug #22540: Incorrect value in column End_log_pos of SHOW BINLOG EVENTS using InnoDB
  
  show that output for SHOW BINLOG EVENTS is no correct
  even within transactions.
parent 56517981
...@@ -32,11 +32,11 @@ Log_name Pos Event_type Server_id End_log_pos Info ...@@ -32,11 +32,11 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4
master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
master-bin.000001 223 Query 1 287 BEGIN master-bin.000001 223 Query 1 287 BEGIN
master-bin.000001 287 Table_map 1 40 table_id: # (test.t1) master-bin.000001 287 Table_map 1 327 table_id: # (test.t1)
master-bin.000001 327 Table_map 1 98 table_id: # (mysql.ndb_apply_status) master-bin.000001 327 Table_map 1 385 table_id: # (mysql.ndb_apply_status)
master-bin.000001 385 Write_rows 1 157 table_id: # master-bin.000001 385 Write_rows 1 444 table_id: #
master-bin.000001 444 Write_rows 1 195 table_id: # master-bin.000001 444 Write_rows 1 482 table_id: #
master-bin.000001 482 Write_rows 1 233 table_id: # flags: STMT_END_F master-bin.000001 482 Write_rows 1 520 table_id: # flags: STMT_END_F
master-bin.000001 520 Query 1 585 COMMIT master-bin.000001 520 Query 1 585 COMMIT
master-bin.000001 585 Query 1 665 use `test`; TRUNCATE TABLE t1 master-bin.000001 585 Query 1 665 use `test`; TRUNCATE TABLE t1
master-bin.000001 665 Query 1 741 use `test`; DROP TABLE t1 master-bin.000001 665 Query 1 741 use `test`; DROP TABLE t1
...@@ -69,27 +69,27 @@ Log_name Pos Event_type Server_id End_log_pos Info ...@@ -69,27 +69,27 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4
master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
master-bin.000001 223 Query 1 287 BEGIN master-bin.000001 223 Query 1 287 BEGIN
master-bin.000001 287 Table_map 1 40 table_id: # (test.t1) master-bin.000001 287 Table_map 1 327 table_id: # (test.t1)
master-bin.000001 327 Table_map 1 98 table_id: # (mysql.ndb_apply_status) master-bin.000001 327 Table_map 1 385 table_id: # (mysql.ndb_apply_status)
master-bin.000001 385 Write_rows 1 157 table_id: # master-bin.000001 385 Write_rows 1 444 table_id: #
master-bin.000001 444 Write_rows 1 195 table_id: # master-bin.000001 444 Write_rows 1 482 table_id: #
master-bin.000001 482 Write_rows 1 233 table_id: # flags: STMT_END_F master-bin.000001 482 Write_rows 1 520 table_id: # flags: STMT_END_F
master-bin.000001 520 Query 1 585 COMMIT master-bin.000001 520 Query 1 585 COMMIT
master-bin.000001 585 Query 1 665 use `test`; TRUNCATE TABLE t1 master-bin.000001 585 Query 1 665 use `test`; TRUNCATE TABLE t1
master-bin.000001 665 Query 1 741 use `test`; DROP TABLE t1 master-bin.000001 665 Query 1 741 use `test`; DROP TABLE t1
master-bin.000001 741 Query 1 858 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 741 Query 1 858 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
master-bin.000001 858 Query 1 922 BEGIN master-bin.000001 858 Query 1 922 BEGIN
master-bin.000001 922 Table_map 1 40 table_id: # (test.t1) master-bin.000001 922 Table_map 1 962 table_id: # (test.t1)
master-bin.000001 962 Table_map 1 98 table_id: # (mysql.ndb_apply_status) master-bin.000001 962 Table_map 1 1020 table_id: # (mysql.ndb_apply_status)
master-bin.000001 1020 Write_rows 1 157 table_id: # master-bin.000001 1020 Write_rows 1 1079 table_id: #
master-bin.000001 1079 Write_rows 1 195 table_id: # master-bin.000001 1079 Write_rows 1 1117 table_id: #
master-bin.000001 1117 Write_rows 1 233 table_id: # flags: STMT_END_F master-bin.000001 1117 Write_rows 1 1155 table_id: # flags: STMT_END_F
master-bin.000001 1155 Query 1 1220 COMMIT master-bin.000001 1155 Query 1 1220 COMMIT
master-bin.000001 1220 Query 1 1284 BEGIN master-bin.000001 1220 Query 1 1284 BEGIN
master-bin.000001 1284 Table_map 1 40 table_id: # (test.t1) master-bin.000001 1284 Table_map 1 1324 table_id: # (test.t1)
master-bin.000001 1324 Table_map 1 98 table_id: # (mysql.ndb_apply_status) master-bin.000001 1324 Table_map 1 1382 table_id: # (mysql.ndb_apply_status)
master-bin.000001 1382 Write_rows 1 157 table_id: # master-bin.000001 1382 Write_rows 1 1441 table_id: #
master-bin.000001 1441 Delete_rows 1 191 table_id: # master-bin.000001 1441 Delete_rows 1 1475 table_id: #
master-bin.000001 1475 Delete_rows 1 225 table_id: # flags: STMT_END_F master-bin.000001 1475 Delete_rows 1 1509 table_id: # flags: STMT_END_F
master-bin.000001 1509 Query 1 1574 COMMIT master-bin.000001 1509 Query 1 1574 COMMIT
master-bin.000001 1574 Query 1 1650 use `test`; DROP TABLE t1 master-bin.000001 1574 Query 1 1650 use `test`; DROP TABLE t1
...@@ -3949,65 +3949,111 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log) ...@@ -3949,65 +3949,111 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
long val; long val;
uchar header[LOG_EVENT_HEADER_LEN]; uchar header[LOG_EVENT_HEADER_LEN];
/*
The events in the buffer have incorrect end_log_pos data
(relative to beginning of group rather than absolute),
so we'll recalculate them in situ so the binlog is always
correct, even in the middle of a group. This is possible
because we now know the start position of the group (the
offset of this cache in the log, if you will); all we need
to do is to find all event-headers, and add the position of
the group to the end_log_pos of each event. This is pretty
straight forward, except that we read the cache in segments,
so an event-header might end up on the cache-border and get
split.
*/
group= my_b_tell(&log_file); group= my_b_tell(&log_file);
hdr_offs= carry= 0; hdr_offs= carry= 0;
do do
{ {
if (likely(carry > 0))
/*
if we only got a partial header in the last iteration,
get the other half now and process a full header.
*/
if (unlikely(carry > 0))
{ {
DBUG_ASSERT(carry < LOG_EVENT_HEADER_LEN); DBUG_ASSERT(carry < LOG_EVENT_HEADER_LEN);
/* assemble both halves */
memcpy(&header[carry], (char *)cache->read_pos, LOG_EVENT_HEADER_LEN - carry); memcpy(&header[carry], (char *)cache->read_pos, LOG_EVENT_HEADER_LEN - carry);
/* fix end_log_pos */
val= uint4korr(&header[LOG_POS_OFFSET]) + group; val= uint4korr(&header[LOG_POS_OFFSET]) + group;
int4store(&header[LOG_POS_OFFSET], val); int4store(&header[LOG_POS_OFFSET], val);
/* write the first half of the split header */
if (my_b_write(&log_file, header, carry)) if (my_b_write(&log_file, header, carry))
return ER_ERROR_ON_WRITE; return ER_ERROR_ON_WRITE;
/*
copy fixed second half of header to cache so the correct
version will be written later.
*/
memcpy((char *)cache->read_pos, &header[carry], LOG_EVENT_HEADER_LEN - carry); memcpy((char *)cache->read_pos, &header[carry], LOG_EVENT_HEADER_LEN - carry);
/* next event header at ... */
hdr_offs = LOG_EVENT_HEADER_LEN - carry + hdr_offs = LOG_EVENT_HEADER_LEN - carry +
uint4korr(&header[EVENT_LEN_OFFSET]); uint4korr(&header[EVENT_LEN_OFFSET]);
carry= 0; carry= 0;
} }
/* if there is anything to write, process it. */
if(likely(bytes > 0)) if(likely(bytes > 0))
{ {
do { /*
DBUG_ASSERT((hdr_offs + max(EVENT_LEN_OFFSET, LOG_POS_OFFSET) + 4) <= bytes); next header beyond current read-buffer? we'll get it later
(though not necessarily in the very next iteration).
*/
val= uint4korr((char *)cache->read_pos + hdr_offs + LOG_POS_OFFSET) + group; if (hdr_offs >= bytes)
int4store((char *)cache->read_pos + hdr_offs + LOG_POS_OFFSET, val); hdr_offs -= bytes;
hdr_offs += uint4korr((char *)cache->read_pos + hdr_offs + EVENT_LEN_OFFSET); else
{
/* header beyond current read-buffer? */ /* process all event-headers in this (partial) cache. */
if (hdr_offs >= bytes)
{
hdr_offs -= bytes;
break;
}
/* split header? */ do {
if (hdr_offs + LOG_EVENT_HEADER_LEN > bytes)
{
carry= bytes - hdr_offs;
memcpy(header, (char *)cache->read_pos + hdr_offs, carry); /*
bytes -= carry; partial header only? save what we can get, process once
} we get the rest.
*/
if (hdr_offs + LOG_EVENT_HEADER_LEN > bytes)
{
carry= bytes - hdr_offs;
memcpy(header, (char *)cache->read_pos + hdr_offs, carry);
bytes= hdr_offs;
}
else
{
/* we've got a full event-header, and it came in one piece */
uchar *log_pos= cache->read_pos + hdr_offs + LOG_POS_OFFSET;
/* fix end_log_pos */
val= uint4korr(log_pos) + group;
int4store(log_pos, val);
/* next event header at ... */
log_pos= (uchar *)cache->read_pos + hdr_offs + EVENT_LEN_OFFSET;
hdr_offs += uint4korr(log_pos);
} while (hdr_offs < bytes); }
} while (hdr_offs < bytes);
}
} }
/* Write data to the binary log file */ /* Write data to the binary log file */
if (my_b_write(&log_file, cache->read_pos, bytes)) if (my_b_write(&log_file, cache->read_pos, bytes))
return ER_ERROR_ON_WRITE; return ER_ERROR_ON_WRITE;
cache->read_pos= cache->read_end; cache->read_pos=cache->read_end; // Mark buffer used up
} while ((bytes= my_b_fill(cache))); } while ((bytes=my_b_fill(cache)));
if (sync_log) if (sync_log)
flush_and_sync(); flush_and_sync();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment