mariadb/mysql-test/suite/rpl/t/rpl_bug31076.test
unknown 8d37a30eac BUG#32407: Impossible to do point-in-time recovery from older binlog
Problem: it is unsafe to read base64-printed events without first
reading the Format_description_log_event (FD).  Currently, mysqlbinlog
cannot print the FD.

As a side effect, another bug has also been fixed: When mysqlbinlog
--start-position=X was specified, no ROLLBACK was printed. I changed
this, so that ROLLBACK is always printed.

This patch does several things:

 - Format_description_log_event (FD) now print themselves in base64
   format.

 - mysqlbinlog is now able to print FD events.  It has three modes:
    --base64-output=auto    Print row events in base64 output, and print
                            FD event.  The FD event is printed even if
                            it is outside the range specified with
                            --start-position, because it would not be
                            safe to read row events otherwise. This is
                            the default.

    --base64-output=always  Like --base64-output=auto, but also print
                            base64 output for query events.  This is
                            like the old --base64-output flag, which
                            is also a shorthand for
                            --base64-output=always

    --base64-output=never   Never print base64 output, generate error if
                            row events occur in binlog.  This is
                            useful to suppress the FD event in binlogs
                            known not to contain row events (e.g.,
                            because BINLOG statement is unsafe,
                            requires root privileges, is not SQL, etc)

 - the BINLOG statement now handles FD events correctly, by setting
   the thread's rli's relay log's description_event_for_exec to the
   loaded event.

   In fact, executing a BINLOG statement is almost the same as reading
   an event from a relay log.  Before my patch, the code for this was
   separated (exec_relay_log_event in slave.cc executes events from
   the relay log, mysql_client_binlog_statement in sql_binlog.cc
   executes BINLOG statements).  I needed to augment
   mysql_client_binlog_statement to do parts of what
   exec_relay_log_event does.  Hence, I did a small refactoring and
   moved parts of exec_relay_log_event to a new function, which I
   named apply_event_and_update_pos.  apply_event_and_update_pos is
   called both from exec_relay_log_event and from
   mysql_client_binlog_statement.

 - When a non-FD event is executed in a BINLOG statement, without
   previously executing a FD event in a BINLOG statement, it generates
   an error, because that's unsafe.  I took a new error code for that:
   ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENTS.

   In order to get a decent error message containing the name of the
   event, I added the class method char*
   Log_event::get_type_str(Log_event_type type), which returns a
   string name for the given Log_event_type.  This is just like the
   existing char* Log_event::get_type_str(), except it is a class
   method that takes the log event type as parameter.

   I also added PRE_GA_*_ROWS_LOG_EVENT to Log_event::get_type_str(),
   so that names of old rows event are properly printed.

 - When reading an event, I added a check that the event type is known
   by the current Format_description_log_event. Without this, it may
   crash on bad input (and I was struck by this several times).

 - I patched the following test cases, which all contain BINLOG
   statements for row events which must be preceded by BINLOG
   statements for FD events:
    - rpl_bug31076

While I was here, I fixed some small things in log_event.cc:

 - replaced hard-coded 4 by EVENT_TYPE_OFFSET in 3 places

 - replaced return by DBUG_VOID_RETURN in one place

 - The name of the logfile can be '-' to indicate stdin.  Before my
   patch, the code just checked if the first character is '-'; now it
   does a full strcmp().  Probably, all arguments that begin with a -
   are already handled somewhere else as flags, but I still think it
   is better that the code reflects what it is supposed to do, with as
   little dependencies as possible on other parts of the code.  If we
   one day implement that all command line arguments after -- are
   files (as most unix tools do), then we need this.

I also fixed the following in slave.cc:

 - next_event() was declared twice, and queue_event was not static but
   should be static (not used outside the file).


client/client_priv.h:
  Declared the new option for base64 output.
client/mysqlbinlog.cc:
   - Change from using the two-state command line option
    "default/--base64-output" to the three-state
    "--base64-output=[never|auto|always]"
   - Print the FD event even if it is outside the --start-position range.
   - Stop if a row event is about to be printed without a preceding FD
     event.
   - Minor fixes:
      * changed 4 to EVENT_TYPE_OFFSET in some places
      * Added comments
      * before, "mysqlbinlog -xyz" read from stdin; now it does not
        (only "mysqlbinlog -" reads stdin).
mysql-test/r/mysqlbinlog2.result:
  Updated result file: mysqlbinlog now prints ROLLBACK always.
mysql-test/suite/binlog/t/disabled.def:
  The test must be disabled since it reveals another bug: see BUG#33247.
mysql-test/suite/rpl/r/rpl_bug31076.result:
  Updated result file
mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result:
  Updated result file
mysql-test/suite/rpl/t/rpl_bug31076.test:
  Had to add explicit Format_description_log_event before other BINLOG
  statements
mysql-test/t/mysqlbinlog2.test:
  we must suppress base64 output in result file because it contains a
  timestamp
sql/log_event.cc:
   - Made FD events able to print themselves
   - Added check that the current FD event knows about the event type, when
     an event is about to be read. (Hint to reviewers: I had to re-indent
     a big block because of this; use diff -b)
      * To get a decent error message, I also added a class method
        const char* Log_event::get_type_str(Log_event_type)
        which converts number to event type string without having a
        Log_event object.
      * Made Log_event::get_type_str aware of PRE_GA_*_ROWS_LOG_EVENT.
   - Minor fixes:
      * Changed return to DBUG_VOID_RETURN
sql/log_event.h:
   - Declared enum to describe the three base64_output modes
   - Use the enum instead of a flag
   - Declare the new class method get_type_str (see log_event.cc)
sql/share/errmsg.txt:
  Added error msg.
sql/slave.cc:
   - Factored out part of exec_relay_log_event to the new function
     apply_event_and_update_pos, because that code is needed when executing
     BINLOG statements. (this is be functionally equivalent to the
     previous code, except: (1) skipping events is now optional, controlled
     by a parameter to the new function (2) the return value of
     exec_relay_log_event has changed; see next item).
   - Changed returned error value to always be 1. Before, it would return
     the error value from apply_log_event, which was unnecessary. This
     change is safe because the exact return value of exec_relay_log_event
     is never examined; it is only tested to be ==0 or !=0.
   - Added comments describing exec_relay_log_event and
     apply_event_and_update_pos.
   - Minor fixes:
      * Removed duplicate declaration of next_event, made queue_event
        static.
      * Added doxygen code to include this file.
sql/slave.h:
  Declared the new apply_event_and_update_pos
sql/sql_binlog.cc:
   - Made mysql_binlog_statement set the current FD event when the given
     event is an FD event. This entails using the new function
     apply_event_and_update_pos from slave.cc instead of just calling the
     ev->apply method.
   - Made mysql_binlog_statement fail if the first BINLOG statement is not
     an FD event.
mysql-test/suite/binlog/r/binlog_base64_flag.result:
  New test file needs new result file
mysql-test/suite/binlog/t/binlog_base64_flag.test:
  Added test case to verify that:
   - my patch fixes the bug
   - the new --base64-output flag works as expected
   - base64 events not preceded by an FD event give an error
   - an event of a type not known by the current FD event fails cleanly.
mysql-test/suite/binlog/std_data/binlog-bug32407.000001:
  BitKeeper file /home/sven/bk/b32407-5.1-new-rpl-mysqlbinlog_base64/mysql-test/suite/binlog/std_data/binlog-bug32407.000001
2007-12-14 19:02:02 +01:00

136 lines
6.9 KiB
Text

source include/master-slave.inc;
CREATE DATABASE track;
USE track;
CREATE TABLE `visits` (
`visits_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`myid` varchar(32) NOT NULL DEFAULT '',
`src` varchar(64) NOT NULL DEFAULT '',
`ip` int(10) unsigned NOT NULL DEFAULT '0',
`cc` char(2) NOT NULL DEFAULT '',
`org` varchar(80) DEFAULT NULL,
`ref` varchar(255) NOT NULL DEFAULT '',
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`host` varchar(30) NOT NULL DEFAULT '',
`entry` varchar(255) NOT NULL DEFAULT '',
`visit_exit` varchar(255) NOT NULL DEFAULT '',
`user_id` int(11) unsigned NOT NULL DEFAULT '0',
`visit_start` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`visits_id`),
KEY `ip` (`ip`),
KEY `time` (`time`),
KEY `user_id` (`user_id`)
) ENGINE=MyISAM AUTO_INCREMENT=21293381 DEFAULT CHARSET=latin1;
CREATE TABLE `visits_events` (
`event_id` mediumint(8) unsigned NOT NULL DEFAULT '0',
`visit_id` int(11) unsigned NOT NULL DEFAULT '0',
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`src` varchar(64) NOT NULL DEFAULT '',
`data` varchar(255) NOT NULL DEFAULT '',
`visits_events_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`visits_events_id`),
KEY `event_id` (`event_id`),
KEY `visit_id` (`visit_id`),
KEY `data` (`data`)
) ENGINE=MyISAM AUTO_INCREMENT=33900731 DEFAULT CHARSET=latin1;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
--delimiter /*!*/;
# at 4 (0x4)
#071204 14:29:31 server id 1 end_log_pos 106
# Position Timestamp Type Master ID Size Master Pos Flags
# 4 3b 56 55 47 0f 01 00 00 00 66 00 00 00 6a 00 00 00 00 00
# 17 04 00 35 2e 31 2e 32 33 2d 72 63 2d 64 65 62 75 |..5.1.23.rc.debu|
# 27 67 2d 6c 6f 67 00 00 00 00 00 00 00 00 00 00 00 |g.log...........|
# 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
# 47 00 00 00 00 3b 56 55 47 13 38 0d 00 08 00 12 00 |.....VUG.8......|
# 57 04 04 04 04 12 00 00 53 00 04 1a 08 00 00 00 08 |.......S........|
# 67 08 08 02 |...|
# Start: binlog v 4, server v 5.1.23-rc-debug-log created 071204 14:29:31 at startup
BINLOG '
O1ZVRw8BAAAAZgAAAGoAAAAAAAQANS4xLjIzLXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAA7VlVHEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
'/*!*/;
# at 164170623
# at 164170679
#7918 3:59:2 server id 436 end_log_pos 164170679
# 9c90b7f 06 4d ef 46 13 b4 01 00 00 38 00 00 00 b7 0b c9 |.M.F.....8......|
# 9c90b8f 09 00 00 99 57 17 02 00 00 00 00 05 74 72 61 63 |....W.......trac|
# 9c90b9f 6b 00 0d 76 69 |k..vi|
# Table_map: `track`.`visits_events` mapped to number 35084185
#7918 3:59:2 server id 436 end_log_pos 164170769
# 9c90bb7 06 4d ef 46 17 b4 01 00 00 5a 00 00 00 11 0c c9 |.M.F.....Z......|
# 9c90bc7 09 10 00 99 57 17 02 00 00 01 00 06 ff c0 20 4e |....W..........N|
# 9c90bd7 00 be f5 43 01 06 4d ef 46 00 2b 44 6f 77 6e 6c |...C..M.F..Downl|
# 9c90be7 6f 61 64 73 2f 4d 79 53 51 4c 2d 34 2e 31 2f 6d |oads.MySQL.4.1.m|
# 9c90bf7 79 73 71 6c 2d 34 2e |ysql.4.|
# Write_rows: table id 35084185 flags: STMT_END_F
BINLOG '
Bk3vRhO0AQAAOAAAALcLyQkAAJlXFwIAAAAABXRyYWNrAA12aXNpdHNfZXZlbnRzAAYJAwcPDwM=
Bk3vRhe0AQAAWgAAABEMyQkQAJlXFwIAAAEABv/AIE4AvvVDAQZN70YAK0Rvd25sb2Fkcy9NeVNR
TC00LjEvbXlzcWwtNC4xLjEyYS13aW4zMi56aXBPaAIC
'/*!*/;
# at 164170769
#7918 3:59:2 server id 436 end_log_pos 164170797
# 9c90c11 06 4d ef 46 05 b4 01 00 00 |.M.F.....|
# Intvar
SET INSERT_ID=21231039/*!*/;
# at 164170797
#7918 3:59:2 server id 436 end_log_pos 164171293
# 9c90c2d 06 4d ef 46 02 b4 01 00 00 f0 01 00 00 1d 0e c9 |.M.F............|
# 9c90c3d 09 10 00 28 80 af 01 00 00 00 00 05 00 00 1f 00 |................|
# 9c90c4d 00 00 40 00 00 01 00 00 00 00 00 00 00 00 06 03 |................|
# 9c90c5d 73 74 64 04 08 00 08 00 08 00 05 03 55 54 43 74 |std.........UTCt|
# 9c90c6d 72 61 63 6b 00 49 4e 53 45 52 54 20 49 4e 54 4f |rack.INSERT.INTO|
# 9c90c7d 20 76 69 73 69 74 73 20 28 6d 79 69 64 2c 20 75 |.visits..myid..u|
# 9c90c8d 73 65 72 5f 69 64 2c 20 73 72 63 2c 20 69 70 2c |ser.id..src..ip.|
# 9c90c9d 20 63 63 2c 20 6f 72 67 2c 20 72 65 66 2c 20 74 |.cc..org..ref..t|
# 9c90cad 69 6d 65 2c 20 68 6f 73 74 2c 20 65 6e 74 72 79 |ime..host..entry|
# 9c90cbd 2c 20 76 69 73 69 74 5f 65 78 69 74 2c 20 76 69 |..visit.exit..vi|
# 9c90ccd 73 69 74 5f 73 74 61 72 74 29 0a 09 09 09 56 41 |sit.start.....VA|
# 9c90cdd 4c 55 45 53 20 28 27 33 6d 33 6c 34 72 68 73 36 |LUES...3m3l4rhs6|
# 9c90ced 64 6f 30 73 66 35 70 31 69 39 6c 72 39 34 67 39 |do0sf5p1i9lr94g9|
# 9c90cfd 32 38 61 32 37 32 76 27 2c 20 27 27 2c 20 27 27 |28a272v.........|
# 9c90d0d 2c 20 49 4e 45 54 5f 41 54 4f 4e 28 27 37 31 2e |..INET.ATON..71.|
# 9c90d1d 31 31 38 2e 31 32 34 2e 39 38 27 29 2c 20 27 27 |118.124.98......|
# 9c90d2d 2c 20 27 27 2c 20 27 68 74 74 70 3a 2f 2f 64 65 |.......http...de|
# 9c90d3d 76 2e 6d 79 73 71 6c 2e 63 6f 6d 2f 64 6f 77 6e |v.mysql.com.down|
# 9c90d4d 6c 6f 61 64 73 2f 63 6f 6e 6e 65 63 74 6f 72 2f |loads.connector.|
# 9c90d5d 6a 2f 33 2e 30 2e 68 74 6d 6c 27 2c 20 4e 55 4c |j.3.0.html...NUL|
# 9c90d6d 4c 2c 20 27 64 65 76 2e 6d 79 73 71 6c 2e 63 6f |L...dev.mysql.co|
# 9c90d7d 6d 27 2c 20 27 2f 67 65 74 2f 44 6f 77 6e 6c 6f |m.....get.Downlo|
# 9c90d8d 61 64 73 2f 43 6f 6e 6e 65 63 74 6f 72 2d 4a 2f |ads.Connector.J.|
# 9c90d9d 6d 79 73 71 6c 2d 63 6f 6e 6e 65 63 74 6f 72 2d |mysql.connector.|
# 9c90dad 6a 61 76 61 2d 33 2e 30 2e 31 37 2d 67 61 2e 7a |java.3.0.17.ga.z|
# 9c90dbd 69 70 2f 66 72 6f 6d 2f 70 69 63 6b 27 2c 20 27 |ip.from.pick....|
# 9c90dcd 2f 67 65 74 2f 44 6f 77 6e 6c 6f 61 64 73 2f 43 |.get.Downloads.C|
# 9c90ddd 6f 6e 6e 65 63 74 6f 72 2d 4a 2f 6d 79 73 71 6c |onnector.J.mysql|
# 9c90ded 2d 63 6f 6e 6e 65 63 74 6f 72 2d 6a 61 76 61 2d |.connector.java.|
# 9c90dfd 33 2e 30 2e 31 37 2d 67 61 2e 7a 69 70 |3.0.17.ga.zip|
# Query thread_id=28278824 exec_time=0 error_code=0
use track/*!*/;
SET TIMESTAMP=1190087942/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
SET @@session.time_zone='UTC'/*!*/;
INSERT INTO visits (myid, user_id, src, ip, cc, org, ref, time, host, entry, visit_exit, visit_start)
VALUES ('3m3l4rhs6do0sf5p1i9lr94g928a272v', '', '', INET_ATON('71.118.124.98'), '', '', 'http://dev.mysql.com/downloads/connector/j/3.0.html', NULL, 'dev.mysql.com', '/get/Downloads/Connector-J/mysql-connector-java-3.0.17-ga.zip/from/pick', '/get/Downloads/Connector-J/mysql-connector-java-3.0.17-ga.zip/from/pick', NOW())/*!*/;
# at 164171293
--delimiter ;
SELECT * FROM visits;
SELECT * FROM visits_events;
# Cleanup
DROP DATABASE track;
sync_slave_with_master;
--echo End of 5.1 tests