Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
0caa1960
Commit
0caa1960
authored
Jul 14, 2011
by
Luis Soares
Browse files
Options
Browse Files
Download
Plain Diff
BUG#11753004
Manual merge from mysql-5.1 into mysql-5.5.
parents
c09c4c3a
bf7d414b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
301 additions
and
12 deletions
+301
-12
mysql-test/suite/rpl/r/rpl_row_corruption.result
mysql-test/suite/rpl/r/rpl_row_corruption.result
+49
-0
mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt
mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt
+1
-0
mysql-test/suite/rpl/t/rpl_row_corruption.test
mysql-test/suite/rpl/t/rpl_row_corruption.test
+115
-0
sql/log_event.cc
sql/log_event.cc
+136
-12
No files found.
mysql-test/suite/rpl/r/rpl_row_corruption.result
0 → 100644
View file @
0caa1960
include/master-slave.inc
[connection master]
CREATE TABLE t1_11753004 (c1 INT);
CREATE TABLE t2_11753004 (c1 INT);
INSERT INTO t1_11753004 VALUES (1);
INSERT INTO t2_11753004 VALUES (2);
call mtr.add_suppression(".*Found table map event mapping table id 0 which was already mapped but with different settings.*");
include/stop_slave.inc
SET @save_debug= @@global.debug;
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
include/start_slave.inc
UPDATE t1_11753004, t2_11753004 SET t1_11753004.c1=3, t2_11753004.c1=4 WHERE t1_11753004.c1=1 OR t2_11753004.c1=2;
include/wait_for_slave_sql_error.inc [errno=1593 ]
include/stop_slave.inc
SET GLOBAL debug="-d,inject_tblmap_same_id_maps_diff_table";
include/start_slave.inc
include/rpl_reset.inc
DROP TABLE t1_11753004, t2_11753004;
include/stop_slave.inc
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
include/start_slave.inc
include/rpl_reset.inc
CREATE TABLE t1_11753004 (c1 INT);
CREATE TABLE t2_11753004_ign (c1 INT);
INSERT INTO t1_11753004 VALUES (1);
INSERT INTO t2_11753004_ign VALUES (2);
UPDATE t1_11753004, t2_11753004_ign SET t1_11753004.c1=3, t2_11753004_ign.c1=4 WHERE t1_11753004.c1=1 OR t2_11753004_ign.c1=2;
CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c1 INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
BINLOG '
SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8=
'/*!*/;
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
BINLOG '
SOgWThMBAAAAKQAAAAYDAAAAAEIAAAAAAAEABHRlc3QAAnQxAAEDAAE=
SOgWThMBAAAAKQAAAC8DAAAAAEMAAAAAAAEABHRlc3QAAnQyAAEDAAE=
SOgWThgBAAAAKAAAAFcDAAAAAEIAAAAAAAAAAf///gEAAAD+AwAAAA==
SOgWThgBAAAAKAAAAH8DAAAAAEMAAAAAAAEAAf///gEAAAD+BAAAAA==
'/*!*/;
ERROR HY000: Fatal error: Found table map event mapping table id 0 which was already mapped but with different settings.
DROP TABLE t1,t2;
SET GLOBAL debug="-d,inject_tblmap_same_id_maps_diff_table";
DROP TABLE t1_11753004;
DROP TABLE t2_11753004_ign;
SET GLOBAL debug= @save_debug;
include/rpl_end.inc
mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt
0 → 100644
View file @
0caa1960
--replicate-ignore-table=test.t2_11753004_ign
mysql-test/suite/rpl/t/rpl_row_corruption.test
0 → 100644
View file @
0caa1960
#
--
source
include
/
master
-
slave
.
inc
--
source
include
/
have_debug
.
inc
--
source
include
/
have_binlog_format_row
.
inc
# BUG#11753004: 44360: REPLICATION FAILED
## assert that we get an error when checking the
## identifiers at the slave (instead of a crash or
## different table being updated)
--
let
$t1
=
t1_11753004
--
let
$t2
=
t2_11753004
--
let
$t2_ign
=
t2_11753004_ign
## test #1: assert that we get an error raised when multiple
## tables in the same RBR statement are mapped with the
## same identifier
--
eval
CREATE
TABLE
$t1
(
c1
INT
)
--
eval
CREATE
TABLE
$t2
(
c1
INT
)
--
eval
INSERT
INTO
$t1
VALUES
(
1
)
--
eval
INSERT
INTO
$t2
VALUES
(
2
)
--
sync_slave_with_master
call
mtr
.
add_suppression
(
".*Found table map event mapping table id 0 which was already mapped but with different settings.*"
);
# stop the slave and inject corruption
--
source
include
/
stop_slave
.
inc
SET
@
save_debug
=
@@
global
.
debug
;
SET
GLOBAL
debug
=
"+d,inject_tblmap_same_id_maps_diff_table"
;
--
source
include
/
start_slave
.
inc
--
connection
master
# both tables get mapped to 0 (in a way, simulating scenario
# originated by BUG#56226)
--
eval
UPDATE
$t1
,
$t2
SET
$t1
.
c1
=
3
,
$t2
.
c1
=
4
WHERE
$t1
.
c1
=
1
OR
$t2
.
c1
=
2
--
connection
slave
# wait for error 1593 (ER_SLAVE_FATAL_ERROR)
--
let
$slave_sql_errno
=
1593
--
source
include
/
wait_for_slave_sql_error
.
inc
--
source
include
/
stop_slave
.
inc
# clean up
SET
GLOBAL
debug
=
"-d,inject_tblmap_same_id_maps_diff_table"
;
--
source
include
/
start_slave
.
inc
--
connection
master
--
source
include
/
rpl_reset
.
inc
--
eval
DROP
TABLE
$t1
,
$t2
--
sync_slave_with_master
## test #2: assert that ignored tables that may have been mapped
## with the same identifier are skipped, thus no error
## is raised.
--
connection
slave
--
source
include
/
stop_slave
.
inc
SET
GLOBAL
debug
=
"+d,inject_tblmap_same_id_maps_diff_table"
;
--
source
include
/
start_slave
.
inc
--
source
include
/
rpl_reset
.
inc
--
connection
master
--
eval
CREATE
TABLE
$t1
(
c1
INT
)
--
eval
CREATE
TABLE
$t2_ign
(
c1
INT
)
--
eval
INSERT
INTO
$t1
VALUES
(
1
)
--
eval
INSERT
INTO
$t2_ign
VALUES
(
2
)
--
eval
UPDATE
$t1
,
$t2_ign
SET
$t1
.
c1
=
3
,
$t2_ign
.
c1
=
4
WHERE
$t1
.
c1
=
1
OR
$t2_ign
.
c1
=
2
# must not raise error as second table is filtered
--
sync_slave_with_master
## test #3: check that BINLOG statements will also raise an
## error if containing table map events mapping different
## tables to same table identifier.
CREATE
TABLE
t1
(
c1
INT
);
CREATE
TABLE
t2
(
c1
INT
);
INSERT
INTO
t1
VALUES
(
1
);
INSERT
INTO
t2
VALUES
(
1
);
# FD event
BINLOG
'
SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8=
'
/*!*/
;
#110708 12:21:44 server id 1 end_log_pos 774 Table_map: `test`.`t1` mapped to number 66
# at 774
#110708 12:21:44 server id 1 end_log_pos 815 Table_map: `test`.`t2` mapped to number 67
# at 815
#110708 12:21:44 server id 1 end_log_pos 855 Update_rows: table id 66
# at 855
#110708 12:21:44 server id 1 end_log_pos 895 Update_rows: table id 67 flags: STMT_END_F
SET
GLOBAL
debug
=
"+d,inject_tblmap_same_id_maps_diff_table"
;
--
error
ER_SLAVE_FATAL_ERROR
BINLOG
'
SOgWThMBAAAAKQAAAAYDAAAAAEIAAAAAAAEABHRlc3QAAnQxAAEDAAE=
SOgWThMBAAAAKQAAAC8DAAAAAEMAAAAAAAEABHRlc3QAAnQyAAEDAAE=
SOgWThgBAAAAKAAAAFcDAAAAAEIAAAAAAAAAAf///gEAAAD+AwAAAA==
SOgWThgBAAAAKAAAAH8DAAAAAEMAAAAAAAEAAf///gEAAAD+BAAAAA==
'
/*!*/
;
# clean up
DROP
TABLE
t1
,
t2
;
--
connection
slave
SET
GLOBAL
debug
=
"-d,inject_tblmap_same_id_maps_diff_table"
;
--
connection
master
--
eval
DROP
TABLE
$t1
--
eval
DROP
TABLE
$t2_ign
--
sync_slave_with_master
SET
GLOBAL
debug
=
@
save_debug
;
--
source
include
/
rpl_end
.
inc
sql/log_event.cc
View file @
0caa1960
...
...
@@ -8387,6 +8387,97 @@ Table_map_log_event::~Table_map_log_event()
*/
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
enum
enum_tbl_map_status
{
/* no duplicate identifier found */
OK_TO_PROCESS
=
0
,
/* this table map must be filtered out */
FILTERED_OUT
=
1
,
/* identifier mapping table with different properties */
SAME_ID_MAPPING_DIFFERENT_TABLE
=
2
,
/* a duplicate identifier was found mapping the same table */
SAME_ID_MAPPING_SAME_TABLE
=
3
};
/*
Checks if this table map event should be processed or not. First
it checks the filtering rules, and then looks for duplicate identifiers
in the existing list of rli->tables_to_lock.
It checks that there hasn't been any corruption by verifying that there
are no duplicate entries with different properties.
In some cases, some binary logs could get corrupted, showing several
tables mapped to the same table_id, 0 (see: BUG#56226). Thus we do this
early sanity check for such cases and avoid that the server crashes
later.
In some corner cases, the master logs duplicate table map events, i.e.,
same id, same database name, same table name (see: BUG#37137). This is
different from the above as it's the same table that is mapped again
to the same identifier. Thus we cannot just check for same ids and
assume that the event is corrupted we need to check every property.
NOTE: in the event that BUG#37137 ever gets fixed, this extra check
will still be valid because we would need to support old binary
logs anyway.
@param rli The relay log info reference.
@param table_list A list element containing the table to check against.
@return OK_TO_PROCESS
if there was no identifier already in rli->tables_to_lock
FILTERED_OUT
if the event is filtered according to the filtering rules
SAME_ID_MAPPING_DIFFERENT_TABLE
if the same identifier already maps a different table in
rli->tables_to_lock
SAME_ID_MAPPING_SAME_TABLE
if the same identifier already maps the same table in
rli->tables_to_lock.
*/
static
enum_tbl_map_status
check_table_map
(
Relay_log_info
const
*
rli
,
RPL_TABLE_LIST
*
table_list
)
{
DBUG_ENTER
(
"check_table_map"
);
enum_tbl_map_status
res
=
OK_TO_PROCESS
;
if
(
rli
->
sql_thd
->
slave_thread
/* filtering is for slave only */
&&
(
!
rpl_filter
->
db_ok
(
table_list
->
db
)
||
(
rpl_filter
->
is_on
()
&&
!
rpl_filter
->
tables_ok
(
""
,
table_list
))))
res
=
FILTERED_OUT
;
else
{
for
(
RPL_TABLE_LIST
*
ptr
=
static_cast
<
RPL_TABLE_LIST
*>
(
rli
->
tables_to_lock
);
ptr
;
ptr
=
static_cast
<
RPL_TABLE_LIST
*>
(
ptr
->
next_local
))
{
if
(
ptr
->
table_id
==
table_list
->
table_id
)
{
if
(
strcmp
(
ptr
->
db
,
table_list
->
db
)
||
strcmp
(
ptr
->
alias
,
table_list
->
table_name
)
||
ptr
->
lock_type
!=
TL_WRITE
)
// the ::do_apply_event always sets TL_WRITE
res
=
SAME_ID_MAPPING_DIFFERENT_TABLE
;
else
res
=
SAME_ID_MAPPING_SAME_TABLE
;
break
;
}
}
}
DBUG_PRINT
(
"debug"
,
(
"check of table map ended up with: %u"
,
res
));
DBUG_RETURN
(
res
);
}
int
Table_map_log_event
::
do_apply_event
(
Relay_log_info
const
*
rli
)
{
RPL_TABLE_LIST
*
table_list
;
...
...
@@ -8413,18 +8504,11 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
tname_mem
,
strlen
(
tname_mem
),
tname_mem
,
TL_WRITE
);
table_list
->
table_id
=
m_table_id
;
table_list
->
table_id
=
DBUG_EVALUATE_IF
(
"inject_tblmap_same_id_maps_diff_table"
,
0
,
m_table_id
)
;
table_list
->
updating
=
1
;
int
error
=
0
;
if
(
rli
->
sql_thd
->
slave_thread
/* filtering is for slave only */
&&
(
!
rpl_filter
->
db_ok
(
table_list
->
db
)
||
(
rpl_filter
->
is_on
()
&&
!
rpl_filter
->
tables_ok
(
""
,
table_list
))))
{
my_free
(
memory
);
}
else
DBUG_PRINT
(
"debug"
,
(
"table: %s is mapped to %u"
,
table_list
->
table_name
,
table_list
->
table_id
));
enum_tbl_map_status
tblmap_status
=
check_table_map
(
rli
,
table_list
);
if
(
tblmap_status
==
OK_TO_PROCESS
)
{
DBUG_ASSERT
(
thd
->
lex
->
query_tables
!=
table_list
);
...
...
@@ -8454,8 +8538,48 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
const_cast
<
Relay_log_info
*>
(
rli
)
->
tables_to_lock_count
++
;
/* 'memory' is freed in clear_tables_to_lock */
}
else
// FILTERED_OUT, SAME_ID_MAPPING_*
{
/*
If mapped already but with different properties, we raise an
error.
If mapped already but with same properties we skip the event.
If filtered out we skip the event.
DBUG_RETURN
(
error
);
In all three cases, we need to free the memory previously
allocated.
*/
if
(
tblmap_status
==
SAME_ID_MAPPING_DIFFERENT_TABLE
)
{
/*
Something bad has happened. We need to stop the slave as strange things
could happen if we proceed: slave crash, wrong table being updated, ...
As a consequence we push an error in this case.
*/
char
buf
[
256
];
my_snprintf
(
buf
,
sizeof
(
buf
),
"Found table map event mapping table id %u which "
"was already mapped but with different settings."
,
table_list
->
table_id
);
if
(
thd
->
slave_thread
)
rli
->
report
(
ERROR_LEVEL
,
ER_SLAVE_FATAL_ERROR
,
ER
(
ER_SLAVE_FATAL_ERROR
),
buf
);
else
/*
For the cases in which a 'BINLOG' statement is set to
execute in a user session
*/
my_printf_error
(
ER_SLAVE_FATAL_ERROR
,
ER
(
ER_SLAVE_FATAL_ERROR
),
MYF
(
0
),
buf
);
}
my_free
(
memory
);
}
DBUG_RETURN
(
tblmap_status
==
SAME_ID_MAPPING_DIFFERENT_TABLE
);
}
Log_event
::
enum_skip_reason
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment