MDEV-14605 Changes to "ON UPDATE CURRENT_TIMESTAMP" fields are not
always logged properly with binlog_row_image=MINIMAL There are two issues fixed in this commit. The first is an observation of a multi-table UPDATE binlogged in row-format in binlog_row_image=MINIMAL mode. While the UPDATE aims at a table with an ON-UPDATE attribute its binlog after-image misses to record also installed default value. The reason for that turns out missed marking of default-capable fields in TABLE::write_set. This is fixed to mark such fields similarly to 10.2's MDEV-10134 patch (db7edfed17efe6) that introduced it. The marking follows up 93d1e5ce0b841bed's idea to exploit TABLE:rpl_write_set introduced there though, and thus does not mess (in 10.1) with the actual MDEV-10134 agenda. The patch makes formerly arg-less TABLE::mark_default_fields_for_write() to accept an argument which would be TABLE:rpl_write_set. The 2nd issue is extra columns in in binlog_row_image=MINIMAL before-image while merely a packed primary key is enough. The test main.mysqlbinlog_row_minimal always had a wrong result recorded. This is fixed to invoke a function that intended for read_set possible filtering and which is called (supposed to) in all type of MDL, UPDATE including; the test results have gotten corrected. At *merging* from 10.1->10.2 the 1st "main" part of the patch is unnecessary since the bug is not observed in 10.2, so only hunks from sql/sql_class.cc are required.
This commit is contained in:
parent
17c75bd272
commit
f9ac7032cb
@ -214,39 +214,36 @@ BEGIN
|
||||
# at 1997
|
||||
#<date> server id 1 end_log_pos 2049 Table_map: `test`.`t2` mapped to number 32
|
||||
# at 2049
|
||||
#<date> server id 1 end_log_pos 2119 Update_rows: table id 32 flags: STMT_END_F
|
||||
#<date> server id 1 end_log_pos 2111 Update_rows: table id 32 flags: STMT_END_F
|
||||
### UPDATE `test`.`t2`
|
||||
### WHERE
|
||||
### @1=10 /* INT meta=0 nullable=0 is_null=0 */
|
||||
### @5=4 /* INT meta=0 nullable=1 is_null=0 */
|
||||
### SET
|
||||
### @5=5 /* INT meta=0 nullable=1 is_null=0 */
|
||||
### UPDATE `test`.`t2`
|
||||
### WHERE
|
||||
### @1=11 /* INT meta=0 nullable=0 is_null=0 */
|
||||
### @5=4 /* INT meta=0 nullable=1 is_null=0 */
|
||||
### SET
|
||||
### @5=5 /* INT meta=0 nullable=1 is_null=0 */
|
||||
### UPDATE `test`.`t2`
|
||||
### WHERE
|
||||
### @1=12 /* INT meta=0 nullable=0 is_null=0 */
|
||||
### @5=NULL /* INT meta=0 nullable=1 is_null=1 */
|
||||
### SET
|
||||
### @5=5 /* INT meta=0 nullable=1 is_null=0 */
|
||||
# at 2119
|
||||
#<date> server id 1 end_log_pos 2188 Query thread_id=4 exec_time=x error_code=0
|
||||
# at 2111
|
||||
#<date> server id 1 end_log_pos 2180 Query thread_id=4 exec_time=x error_code=0
|
||||
SET TIMESTAMP=X/*!*/;
|
||||
COMMIT
|
||||
/*!*/;
|
||||
# at 2188
|
||||
#<date> server id 1 end_log_pos 2226 GTID 0-1-9
|
||||
# at 2180
|
||||
#<date> server id 1 end_log_pos 2218 GTID 0-1-9
|
||||
/*!100001 SET @@session.gtid_seq_no=9*//*!*/;
|
||||
BEGIN
|
||||
/*!*/;
|
||||
# at 2226
|
||||
#<date> server id 1 end_log_pos 2278 Table_map: `test`.`t1` mapped to number 31
|
||||
# at 2278
|
||||
#<date> server id 1 end_log_pos 2328 Delete_rows: table id 31 flags: STMT_END_F
|
||||
# at 2218
|
||||
#<date> server id 1 end_log_pos 2270 Table_map: `test`.`t1` mapped to number 31
|
||||
# at 2270
|
||||
#<date> server id 1 end_log_pos 2320 Delete_rows: table id 31 flags: STMT_END_F
|
||||
### DELETE FROM `test`.`t1`
|
||||
### WHERE
|
||||
### @1=10 /* INT meta=0 nullable=0 is_null=0 */
|
||||
@ -259,20 +256,20 @@ BEGIN
|
||||
### DELETE FROM `test`.`t1`
|
||||
### WHERE
|
||||
### @1=13 /* INT meta=0 nullable=0 is_null=0 */
|
||||
# at 2328
|
||||
#<date> server id 1 end_log_pos 2397 Query thread_id=4 exec_time=x error_code=0
|
||||
# at 2320
|
||||
#<date> server id 1 end_log_pos 2389 Query thread_id=4 exec_time=x error_code=0
|
||||
SET TIMESTAMP=X/*!*/;
|
||||
COMMIT
|
||||
/*!*/;
|
||||
# at 2397
|
||||
#<date> server id 1 end_log_pos 2435 GTID 0-1-10
|
||||
# at 2389
|
||||
#<date> server id 1 end_log_pos 2427 GTID 0-1-10
|
||||
/*!100001 SET @@session.gtid_seq_no=10*//*!*/;
|
||||
BEGIN
|
||||
/*!*/;
|
||||
# at 2435
|
||||
#<date> server id 1 end_log_pos 2487 Table_map: `test`.`t2` mapped to number 32
|
||||
# at 2487
|
||||
#<date> server id 1 end_log_pos 2537 Delete_rows: table id 32 flags: STMT_END_F
|
||||
# at 2427
|
||||
#<date> server id 1 end_log_pos 2479 Table_map: `test`.`t2` mapped to number 32
|
||||
# at 2479
|
||||
#<date> server id 1 end_log_pos 2529 Delete_rows: table id 32 flags: STMT_END_F
|
||||
### DELETE FROM `test`.`t2`
|
||||
### WHERE
|
||||
### @1=10 /* INT meta=0 nullable=0 is_null=0 */
|
||||
@ -285,13 +282,76 @@ BEGIN
|
||||
### DELETE FROM `test`.`t2`
|
||||
### WHERE
|
||||
### @1=13 /* INT meta=0 nullable=0 is_null=0 */
|
||||
# at 2537
|
||||
#<date> server id 1 end_log_pos 2606 Query thread_id=4 exec_time=x error_code=0
|
||||
# at 2529
|
||||
#<date> server id 1 end_log_pos 2598 Query thread_id=4 exec_time=x error_code=0
|
||||
SET TIMESTAMP=X/*!*/;
|
||||
COMMIT
|
||||
/*!*/;
|
||||
# at 2606
|
||||
#<date> server id 1 end_log_pos 2650 Rotate to master-bin.000002 pos: 4
|
||||
# at 2598
|
||||
#<date> server id 1 end_log_pos 2642 Rotate to master-bin.000002 pos: 4
|
||||
DELIMITER ;
|
||||
# End of log file
|
||||
ROLLBACK /* added by mysqlbinlog */;
|
||||
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
|
||||
DROP TABLE t1,t2;
|
||||
CREATE TABLE `t1` (
|
||||
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`is_deleted` BIT(1) DEFAULT b'0',
|
||||
`last_updated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`ref_id` BIGINT(20) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `last_updated_KEY` (`last_updated`)
|
||||
);
|
||||
CREATE TABLE `t2` (
|
||||
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`short_desc` VARCHAR(50) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
INSERT INTO t2 (id, short_desc) VALUES (1, 'test');
|
||||
INSERT INTO t1 (id, is_deleted, ref_id) VALUES (1, b'0', 1);
|
||||
FLUSH BINARY LOGS;
|
||||
UPDATE t1 t1 INNER JOIN t2 t2 ON t1.ref_id = t2.id
|
||||
SET t1.is_deleted = TRUE
|
||||
WHERE t1.id = 1;
|
||||
FLUSH BINARY LOGS;
|
||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
|
||||
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
|
||||
DELIMITER /*!*/;
|
||||
# at 368
|
||||
#<date> server id 1 end_log_pos 406 GTID 0-1-16
|
||||
/*!100101 SET @@session.skip_parallel_replication=0*//*!*/;
|
||||
/*!100001 SET @@session.gtid_domain_id=0*//*!*/;
|
||||
/*!100001 SET @@session.server_id=1*//*!*/;
|
||||
/*!100001 SET @@session.gtid_seq_no=16*//*!*/;
|
||||
BEGIN
|
||||
/*!*/;
|
||||
# at 406
|
||||
#<date> server id 1 end_log_pos 453 Table_map: `test`.`t1` mapped to number 34
|
||||
# at 453
|
||||
#<date> server id 1 end_log_pos 498 Update_rows: table id 34 flags: STMT_END_F
|
||||
### UPDATE `test`.`t1`
|
||||
### WHERE
|
||||
### @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */
|
||||
### SET
|
||||
### @2=b'1' /* BIT(1) meta=1 nullable=1 is_null=0 */
|
||||
### @3=X /* TIMESTAMP(0) meta=0 nullable=0 is_null=0 */
|
||||
# at 498
|
||||
#<date> server id 1 end_log_pos 576 Query thread_id=4 exec_time=x error_code=0
|
||||
SET TIMESTAMP=X/*!*/;
|
||||
SET @@session.pseudo_thread_id=4/*!*/;
|
||||
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
|
||||
SET @@session.sql_mode=1342177280/*!*/;
|
||||
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
|
||||
/*!\C latin1 *//*!*/;
|
||||
SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
|
||||
SET @@session.lc_time_names=0/*!*/;
|
||||
SET @@session.collation_database=DEFAULT/*!*/;
|
||||
COMMIT
|
||||
/*!*/;
|
||||
# at 576
|
||||
#<date> server id 1 end_log_pos 620 Rotate to master-bin.000004 pos: 4
|
||||
DELIMITER ;
|
||||
# End of log file
|
||||
ROLLBACK /* added by mysqlbinlog */;
|
||||
|
@ -26,8 +26,49 @@ DELETE FROM t2;
|
||||
--let $datadir = `SELECT @@datadir`
|
||||
|
||||
FLUSH BINARY LOGS;
|
||||
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--replace_regex /\d{6} *\d*:\d\d:\d\d/<date>/ /Start:.*at startup/Start: xxx/ /SET TIMESTAMP=\d*/SET TIMESTAMP=X/ /exec_time=\d*/exec_time=x/
|
||||
--exec $MYSQL_BINLOG --verbose --verbose --base64-output=DECODE-ROWS $datadir/$binlog
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
#
|
||||
# MDEV-14605 ON UPDATE CURRENT_TIMESTAMP fields by multi-table UPDATE are not logged with binlog_row_image=MINIMAL
|
||||
#
|
||||
|
||||
CREATE TABLE `t1` (
|
||||
|
||||
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`is_deleted` BIT(1) DEFAULT b'0',
|
||||
`last_updated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`ref_id` BIGINT(20) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `last_updated_KEY` (`last_updated`)
|
||||
);
|
||||
|
||||
CREATE TABLE `t2` (
|
||||
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`short_desc` VARCHAR(50) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO t2 (id, short_desc) VALUES (1, 'test');
|
||||
INSERT INTO t1 (id, is_deleted, ref_id) VALUES (1, b'0', 1);
|
||||
FLUSH BINARY LOGS;
|
||||
--let $binlog_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
|
||||
|
||||
UPDATE t1 t1 INNER JOIN t2 t2 ON t1.ref_id = t2.id
|
||||
SET t1.is_deleted = TRUE
|
||||
WHERE t1.id = 1;
|
||||
|
||||
--let $binlog = query_get_value(SHOW MASTER STATUS, File, 1)
|
||||
|
||||
FLUSH BINARY LOGS;
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--replace_regex /\d{6} *\d*:\d\d:\d\d/<date>/ /SET TIMESTAMP=\d*/SET TIMESTAMP=X/ /exec_time=\d*/exec_time=x/ /@3=\d*/@3=X/ /CRC32 0x[0-9a-f]+/CRC32 XXX/
|
||||
--exec $MYSQL_BINLOG --verbose --verbose --base64-output=DECODE-ROWS $datadir/$binlog --start-position=$binlog_pos
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
|
@ -6390,6 +6390,22 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
|
||||
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
|
||||
((WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()));
|
||||
|
||||
/**
|
||||
Save a reference to the original read bitmaps
|
||||
We will need this to restore the bitmaps at the end as
|
||||
binlog_prepare_row_images() may change table->read_set.
|
||||
table->read_set is used by pack_row and deep in
|
||||
binlog_prepare_pending_events().
|
||||
*/
|
||||
MY_BITMAP *old_read_set= table->read_set;
|
||||
|
||||
/**
|
||||
This will remove spurious fields required during execution but
|
||||
not needed for binlogging. This is done according to the:
|
||||
binlog-row-image option.
|
||||
*/
|
||||
binlog_prepare_row_images(table);
|
||||
|
||||
size_t const before_maxlen = max_row_length(table, before_record);
|
||||
size_t const after_maxlen = max_row_length(table, after_record);
|
||||
|
||||
@ -6431,6 +6447,9 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
|
||||
int error= ev->add_row_data(before_row, before_size) ||
|
||||
ev->add_row_data(after_row, after_size);
|
||||
|
||||
/* restore read set for the rest of execution */
|
||||
table->column_bitmaps_set_no_signal(old_read_set,
|
||||
table->write_set);
|
||||
return error;
|
||||
|
||||
}
|
||||
|
@ -6137,6 +6137,8 @@ void TABLE::mark_columns_per_binlog_row_image()
|
||||
mark_columns_used_by_index_no_reset(s->primary_key, read_set);
|
||||
/* Only write columns that have changed */
|
||||
rpl_write_set= write_set;
|
||||
if (default_field)
|
||||
mark_default_fields_for_write(rpl_write_set);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -6283,7 +6285,7 @@ bool TABLE::has_default_function(bool is_update)
|
||||
Add all fields that have a default function to the table write set.
|
||||
*/
|
||||
|
||||
void TABLE::mark_default_fields_for_write()
|
||||
void TABLE::mark_default_fields_for_write(MY_BITMAP* bset)
|
||||
{
|
||||
Field **dfield_ptr, *dfield;
|
||||
enum_sql_command cmd= in_use->lex->sql_command;
|
||||
@ -6294,7 +6296,7 @@ void TABLE::mark_default_fields_for_write()
|
||||
dfield->has_insert_default_function()) ||
|
||||
((sql_command_flags[cmd] & CF_UPDATES_DATA) &&
|
||||
dfield->has_update_default_function()))
|
||||
bitmap_set_bit(write_set, dfield->field_index);
|
||||
bitmap_set_bit(bset, dfield->field_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1353,7 +1353,11 @@ public:
|
||||
void mark_columns_per_binlog_row_image(void);
|
||||
bool mark_virtual_col(Field *field);
|
||||
void mark_virtual_columns_for_write(bool insert_fl);
|
||||
void mark_default_fields_for_write();
|
||||
void mark_default_fields_for_write(MY_BITMAP* bset);
|
||||
inline void mark_default_fields_for_write()
|
||||
{
|
||||
mark_default_fields_for_write(write_set);
|
||||
}
|
||||
bool has_default_function(bool is_update);
|
||||
inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
|
||||
MY_BITMAP *write_set_arg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user