mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-24959: ER_BINLOG_ROW_LOGGING_FAILED (1534: Writing one row to the row-based binary log failed)
The Write_rows_log_event originally allocated the m_rows_buf up-front, and thus is_valid() checks that the buffer is allocated correctly. But at some point this was changed to allocate the buffer lazily on demand. This means that a a valid event can now have m_rows_buf==NULL. The is_valid() code was not changed, and thus is_valid() could return false on a valid event. This caused a bug for REPLACE INTO t() VALUES(), () which generates a write_rows event with no after image; then the m_rows_buf was never allocated and is_valid() incorrectly returned false, causing an error in some other parts of the code. Also fix a couple of missing special cases in the code for mysqlbinlog to correctly decode (in comments) row events with missing after image. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
parent
b4fde50b1f
commit
2ab10fbec2
4 changed files with 82 additions and 4 deletions
|
@ -1314,3 +1314,21 @@ a b
|
|||
2 2023-07-22 00:36:20.567890
|
||||
DROP TABLE t;
|
||||
SET time_zone= default;
|
||||
#
|
||||
# MDEV-24959: ER_BINLOG_ROW_LOGGING_FAILED (1534: Writing one row to the row-based binary log failed)
|
||||
#
|
||||
SET SESSION binlog_format= ROW;
|
||||
SET SESSION binlog_row_image= MINIMAL;
|
||||
RESET MASTER;
|
||||
CREATE TABLE t1 (a INT NOT NULL DEFAULT 0 PRIMARY KEY);
|
||||
REPLACE INTO t1 () VALUES (),();
|
||||
DROP TABLE t1;
|
||||
FLUSH BINARY LOGS;
|
||||
SET SESSION binlog_format= STATEMENT;
|
||||
SET SESSION binlog_row_image= default;
|
||||
FOUND 1 /Number of rows: 2/ in mdev24959_1.txt
|
||||
FOUND 1 /DROP TABLE/ in mdev24959_1.txt
|
||||
FOUND 1 /Number of rows: 2/ in mdev24959_2.txt
|
||||
FOUND 1 /DROP TABLE/ in mdev24959_2.txt
|
||||
FOUND 1 /INSERT INTO .* VALUES/ in mdev24959_2.txt
|
||||
FOUND 1 /SET /[*] no columns [*]// in mdev24959_2.txt
|
||||
|
|
|
@ -671,3 +671,48 @@ SELECT * FROM t;
|
|||
SELECT * FROM t;
|
||||
DROP TABLE t;
|
||||
SET time_zone= default;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24959: ER_BINLOG_ROW_LOGGING_FAILED (1534: Writing one row to the row-based binary log failed)
|
||||
--echo #
|
||||
|
||||
SET SESSION binlog_format= ROW;
|
||||
SET SESSION binlog_row_image= MINIMAL;
|
||||
|
||||
RESET MASTER;
|
||||
CREATE TABLE t1 (a INT NOT NULL DEFAULT 0 PRIMARY KEY);
|
||||
REPLACE INTO t1 () VALUES (),();
|
||||
DROP TABLE t1;
|
||||
FLUSH BINARY LOGS;
|
||||
SET SESSION binlog_format= STATEMENT;
|
||||
SET SESSION binlog_row_image= default;
|
||||
|
||||
--exec $MYSQL_BINLOG --base64-output=decode-rows $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mdev24959_1.txt
|
||||
--exec $MYSQL_BINLOG --base64-output=decode-rows --verbose $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mdev24959_2.txt
|
||||
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mdev24959_1.txt
|
||||
--let SEARCH_ABORT= NOT FOUND
|
||||
--let SEARCH_PATTERN= Number of rows: 2
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
# There was a bug that mysqlbinlog would get an error while decoding the
|
||||
# update rows event with no after image and abort the dump; test that now
|
||||
# the dump is complete and includes the final DROP TABLE.
|
||||
--let SEARCH_PATTERN= DROP TABLE
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mdev24959_2.txt
|
||||
--let SEARCH_PATTERN= Number of rows: 2
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_PATTERN= DROP TABLE
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_PATTERN= INSERT INTO .* VALUES
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= SET /[*] no columns [*]/
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mdev24959_1.txt
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mdev24959_2.txt
|
||||
|
|
|
@ -5086,7 +5086,7 @@ public:
|
|||
*/
|
||||
bool is_valid() const override
|
||||
{
|
||||
return m_rows_buf && m_cols.bitmap;
|
||||
return m_cols.bitmap;
|
||||
}
|
||||
|
||||
uint m_row_count; /* The number of rows added to the event */
|
||||
|
|
|
@ -1384,6 +1384,13 @@ void Rows_log_event::count_row_events(PRINT_EVENT_INFO *print_event_info)
|
|||
|
||||
switch (general_type_code) {
|
||||
case WRITE_ROWS_EVENT:
|
||||
/*
|
||||
A write rows event containing no after image (can happen for REPLACE
|
||||
INTO t() VALUES ()), count this correctly as 1 row and no 0.
|
||||
*/
|
||||
if (unlikely(m_rows_buf == m_rows_end))
|
||||
print_event_info->row_events++;
|
||||
/* Fall through. */
|
||||
case DELETE_ROWS_EVENT:
|
||||
row_events= 1;
|
||||
break;
|
||||
|
@ -1509,6 +1516,7 @@ bool Rows_log_event::print_verbose(IO_CACHE *file,
|
|||
/* If the write rows event contained no values for the AI */
|
||||
if (((general_type_code == WRITE_ROWS_EVENT) && (m_rows_buf==m_rows_end)))
|
||||
{
|
||||
print_event_info->row_events++;
|
||||
if (my_b_printf(file, "### INSERT INTO %`s.%`s VALUES ()\n",
|
||||
map->get_db_name(), map->get_table_name()))
|
||||
goto err;
|
||||
|
@ -1542,9 +1550,16 @@ bool Rows_log_event::print_verbose(IO_CACHE *file,
|
|||
/* Print the second image (for UPDATE only) */
|
||||
if (sql_clause2)
|
||||
{
|
||||
if (!(length= print_verbose_one_row(file, td, print_event_info,
|
||||
&m_cols_ai, value,
|
||||
(const uchar*) sql_clause2)))
|
||||
/* If the update rows event contained no values for the AI */
|
||||
if (unlikely(bitmap_is_clear_all(&m_cols_ai)))
|
||||
{
|
||||
length= (bitmap_bits_set(&m_cols_ai) + 7) / 8;
|
||||
if (my_b_printf(file, "### SET /* no columns */\n"))
|
||||
goto err;
|
||||
}
|
||||
else if (!(length= print_verbose_one_row(file, td, print_event_info,
|
||||
&m_cols_ai, value,
|
||||
(const uchar*) sql_clause2)))
|
||||
goto err;
|
||||
value+= length;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue