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
c2b0410c
Commit
c2b0410c
authored
Oct 30, 2007
by
aelkin@dl145j.mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
manual merge
parent
01f86563
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
8 additions
and
453 deletions
+8
-453
mysql-test/r/rpl_slave_skip.result
mysql-test/r/rpl_slave_skip.result
+0
-144
mysql-test/t/rpl_slave_skip-slave.opt
mysql-test/t/rpl_slave_skip-slave.opt
+0
-1
mysql-test/t/rpl_slave_skip.test
mysql-test/t/rpl_slave_skip.test
+0
-203
sql/slave.cc
sql/slave.cc
+8
-105
No files found.
mysql-test/r/rpl_slave_skip.result
deleted
100644 → 0
View file @
01f86563
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
**** On Master ****
CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB;
CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM;
==== Skipping normal transactions ====
**** On Slave ****
STOP SLAVE;
**** On Master ****
BEGIN;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (4, 'master,slave');
INSERT INTO t1 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, 'master,slave');
COMMIT;
SELECT * FROM t1 ORDER BY a;
a b
1 master
2 master
3 master
4 master,slave
5 master,slave
6 master,slave
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
SELECT * FROM t1 ORDER BY a;
a b
4 master,slave
5 master,slave
6 master,slave
**** On Master ****
DELETE FROM t1;
==== Skipping two normal transactions ====
**** On Slave ****
STOP SLAVE;
**** On Master ****
BEGIN;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (4, 'master');
INSERT INTO t1 VALUES (5, 'master');
INSERT INTO t1 VALUES (6, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (7, 'master,slave');
INSERT INTO t1 VALUES (8, 'master,slave');
INSERT INTO t1 VALUES (9, 'master,slave');
COMMIT;
SELECT * FROM t1 ORDER BY a;
a b
1 master
2 master
3 master
4 master
5 master
6 master
7 master,slave
8 master,slave
9 master,slave
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8;
START SLAVE;
SELECT * FROM t1 ORDER BY a;
a b
7 master,slave
8 master,slave
9 master,slave
**** On Master ****
DELETE FROM t1;
==== Skipping without autocommit ====
**** On Slave ****
STOP SLAVE;
**** On Master ****
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
INSERT INTO t1 VALUES (4, 'master,slave');
INSERT INTO t1 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, 'master,slave');
COMMIT;
SELECT * FROM t1 ORDER BY a;
a b
1 master
2 master
3 master
4 master,slave
5 master,slave
6 master,slave
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
SELECT * FROM t1 ORDER BY a;
a b
4 master,slave
5 master,slave
6 master,slave
==== Rollback of transaction with non-transactional change ====
**** On Master ****
DELETE FROM t1;
SET AUTOCOMMIT=1;
**** On Slave ****
STOP SLAVE;
**** On Master ****
BEGIN;
INSERT INTO t1 VALUES (1, '');
INSERT INTO t2 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, '');
ROLLBACK;
BEGIN;
INSERT INTO t1 VALUES (4, '');
INSERT INTO t2 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, '');
ROLLBACK;
SELECT * FROM t1 ORDER BY a;
a b
SELECT * FROM t2 ORDER BY a;
a b
2 master
5 master,slave
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
SELECT * FROM t1 ORDER BY a;
a b
SELECT * FROM t2 ORDER BY a;
a b
5 master,slave
==== Cleanup ====
**** On Master ****
DROP TABLE t1, t2;
mysql-test/t/rpl_slave_skip-slave.opt
deleted
100644 → 0
View file @
01f86563
--innodb
mysql-test/t/rpl_slave_skip.test
deleted
100644 → 0
View file @
01f86563
source
include
/
have_innodb
.
inc
;
source
include
/
master
-
slave
.
inc
;
# This test is for checking that the use of SQL_SLAVE_SKIP_COUNTER
# behaves as expected, i.e., that it is guaranteed to skip an entire
# group and not start executing in the middle of a transaction.
# We are checking the correct behaviour when using both a
# transactional and non-transactional table. The non-transactional
# table comes into play when rolling back a transaction containing a
# write to this table. In that case, the transaction should still be
# written to the binary log, and the slave will apply it and then roll
# it back to get the non-transactional change into the table.
--
echo
****
On
Master
****
CREATE
TABLE
t1
(
a
INT
,
b
SET
(
'master'
,
'slave'
))
ENGINE
=
INNODB
;
CREATE
TABLE
t2
(
a
INT
,
b
SET
(
'master'
,
'slave'
))
ENGINE
=
MYISAM
;
--
echo
====
Skipping
normal
transactions
====
--
echo
****
On
Slave
****
sync_slave_with_master
;
STOP
SLAVE
;
source
include
/
wait_for_slave_to_stop
.
inc
;
--
echo
****
On
Master
****
connection
master
;
BEGIN
;
INSERT
INTO
t1
VALUES
(
1
,
'master'
);
INSERT
INTO
t1
VALUES
(
2
,
'master'
);
INSERT
INTO
t1
VALUES
(
3
,
'master'
);
COMMIT
;
BEGIN
;
INSERT
INTO
t1
VALUES
(
4
,
'master,slave'
);
INSERT
INTO
t1
VALUES
(
5
,
'master,slave'
);
INSERT
INTO
t1
VALUES
(
6
,
'master,slave'
);
COMMIT
;
save_master_pos
;
SELECT
*
FROM
t1
ORDER
BY
a
;
# This will skip a begin event and the first INSERT of the
# transaction, and it should keep skipping until it has reached the
# transaction terminator.
--
echo
****
On
Slave
****
connection
slave
;
SET
GLOBAL
SQL_SLAVE_SKIP_COUNTER
=
2
;
START
SLAVE
;
source
include
/
wait_for_slave_to_start
.
inc
;
sync_with_master
;
SELECT
*
FROM
t1
ORDER
BY
a
;
--
echo
****
On
Master
****
connection
master
;
DELETE
FROM
t1
;
sync_slave_with_master
;
--
echo
====
Skipping
two
normal
transactions
====
--
echo
****
On
Slave
****
connection
slave
;
STOP
SLAVE
;
source
include
/
wait_for_slave_to_stop
.
inc
;
--
echo
****
On
Master
****
connection
master
;
BEGIN
;
INSERT
INTO
t1
VALUES
(
1
,
'master'
);
INSERT
INTO
t1
VALUES
(
2
,
'master'
);
INSERT
INTO
t1
VALUES
(
3
,
'master'
);
COMMIT
;
BEGIN
;
INSERT
INTO
t1
VALUES
(
4
,
'master'
);
INSERT
INTO
t1
VALUES
(
5
,
'master'
);
INSERT
INTO
t1
VALUES
(
6
,
'master'
);
COMMIT
;
BEGIN
;
INSERT
INTO
t1
VALUES
(
7
,
'master,slave'
);
INSERT
INTO
t1
VALUES
(
8
,
'master,slave'
);
INSERT
INTO
t1
VALUES
(
9
,
'master,slave'
);
COMMIT
;
save_master_pos
;
SELECT
*
FROM
t1
ORDER
BY
a
;
# This will skip a begin event and the first INSERT of the
# transaction, and it should keep skipping until it has reached the
# transaction terminator.
--
echo
****
On
Slave
****
connection
slave
;
SET
GLOBAL
SQL_SLAVE_SKIP_COUNTER
=
8
;
START
SLAVE
;
source
include
/
wait_for_slave_to_start
.
inc
;
sync_with_master
;
SELECT
*
FROM
t1
ORDER
BY
a
;
--
echo
****
On
Master
****
connection
master
;
DELETE
FROM
t1
;
sync_slave_with_master
;
--
echo
====
Skipping
without
autocommit
====
# Testing without using autocommit instead. It should still write a
# BEGIN event, so the behaviour should be the same
--
echo
****
On
Slave
****
connection
slave
;
STOP
SLAVE
;
source
include
/
wait_for_slave_to_stop
.
inc
;
--
echo
****
On
Master
****
connection
master
;
SET
AUTOCOMMIT
=
0
;
INSERT
INTO
t1
VALUES
(
1
,
'master'
);
INSERT
INTO
t1
VALUES
(
2
,
'master'
);
INSERT
INTO
t1
VALUES
(
3
,
'master'
);
COMMIT
;
INSERT
INTO
t1
VALUES
(
4
,
'master,slave'
);
INSERT
INTO
t1
VALUES
(
5
,
'master,slave'
);
INSERT
INTO
t1
VALUES
(
6
,
'master,slave'
);
COMMIT
;
save_master_pos
;
SELECT
*
FROM
t1
ORDER
BY
a
;
# This will skip a begin event and the first INSERT of the
# transaction, and it should keep skipping until it has reached the
# transaction terminator.
--
echo
****
On
Slave
****
connection
slave
;
SET
GLOBAL
SQL_SLAVE_SKIP_COUNTER
=
2
;
START
SLAVE
;
source
include
/
wait_for_slave_to_start
.
inc
;
sync_with_master
;
SELECT
*
FROM
t1
ORDER
BY
a
;
# Testing with a non-transactional table in the transaction. This will
# log a ROLLBACK as a transaction terminator, which is a normal Query
# log event.
--
echo
====
Rollback
of
transaction
with
non
-
transactional
change
====
--
echo
****
On
Master
****
connection
master
;
DELETE
FROM
t1
;
SET
AUTOCOMMIT
=
1
;
--
echo
****
On
Slave
****
sync_slave_with_master
;
STOP
SLAVE
;
source
include
/
wait_for_slave_to_stop
.
inc
;
--
echo
****
On
Master
****
connection
master
;
disable_warnings
;
BEGIN
;
INSERT
INTO
t1
VALUES
(
1
,
''
);
INSERT
INTO
t2
VALUES
(
2
,
'master'
);
INSERT
INTO
t1
VALUES
(
3
,
''
);
ROLLBACK
;
BEGIN
;
INSERT
INTO
t1
VALUES
(
4
,
''
);
INSERT
INTO
t2
VALUES
(
5
,
'master,slave'
);
INSERT
INTO
t1
VALUES
(
6
,
''
);
ROLLBACK
;
enable_warnings
;
save_master_pos
;
SELECT
*
FROM
t1
ORDER
BY
a
;
SELECT
*
FROM
t2
ORDER
BY
a
;
--
echo
****
On
Slave
****
connection
slave
;
SET
GLOBAL
SQL_SLAVE_SKIP_COUNTER
=
2
;
START
SLAVE
;
source
include
/
wait_for_slave_to_start
.
inc
;
sync_with_master
;
SELECT
*
FROM
t1
ORDER
BY
a
;
SELECT
*
FROM
t2
ORDER
BY
a
;
--
echo
====
Cleanup
====
--
echo
****
On
Master
****
connection
master
;
DROP
TABLE
t1
,
t2
;
sync_slave_with_master
;
sql/slave.cc
View file @
c2b0410c
...
@@ -1804,6 +1804,14 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
...
@@ -1804,6 +1804,14 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
int
const
type_code
=
ev
->
get_type_code
();
int
const
type_code
=
ev
->
get_type_code
();
int
exec_res
=
0
;
int
exec_res
=
0
;
DBUG_PRINT
(
"exec_event"
,(
"%s(type_code: %d; server_id: %d)"
,
ev
->
get_type_str
(),
type_code
,
ev
->
server_id
));
DBUG_PRINT
(
"info"
,
(
"thd->options: %s%s; rli->last_event_start_time: %lu"
,
FLAGSTR
(
thd
->
options
,
OPTION_NOT_AUTOCOMMIT
),
FLAGSTR
(
thd
->
options
,
OPTION_BEGIN
),
rli
->
last_event_start_time
));
/*
/*
Execute the event to change the database and update the binary
Execute the event to change the database and update the binary
log coordinates, but first we set some data that is needed for
log coordinates, but first we set some data that is needed for
...
@@ -1828,111 +1836,6 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
...
@@ -1828,111 +1836,6 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
has a Rotate etc).
has a Rotate etc).
*/
*/
DBUG_PRINT
(
"info"
,(
"type_code: %d; server_id: %d; slave_skip_counter: %d"
,
type_code
,
ev
->
server_id
,
rli
->
slave_skip_counter
));
DBUG_PRINT
(
"info"
,
(
"thd->options: %s%s; rli->last_event_start_time: %lu"
,
FLAGSTR
(
thd
->
options
,
OPTION_NOT_AUTOCOMMIT
),
FLAGSTR
(
thd
->
options
,
OPTION_BEGIN
),
rli
->
last_event_start_time
));
/*
If the slave skip counter is positive, we still need to set the
OPTION_BEGIN flag correctly and not skip the log events that
start or end a transaction. If we do this, the slave will not
notice that it is inside a transaction, and happily start
executing from inside the transaction.
Note that the code block below is strictly 5.0.
*/
#if MYSQL_VERSION_ID < 50100
if
(
unlikely
(
rli
->
slave_skip_counter
>
0
))
{
switch
(
type_code
)
{
case
QUERY_EVENT
:
{
Query_log_event
*
const
qev
=
(
Query_log_event
*
)
ev
;
DBUG_PRINT
(
"info"
,
(
"QUERY_EVENT { query: '%s', q_len: %u }"
,
qev
->
query
,
qev
->
q_len
));
if
(
memcmp
(
"BEGIN"
,
qev
->
query
,
qev
->
q_len
+
1
)
==
0
)
thd
->
options
|=
OPTION_BEGIN
;
else
if
(
memcmp
(
"COMMIT"
,
qev
->
query
,
qev
->
q_len
+
1
)
==
0
||
memcmp
(
"ROLLBACK"
,
qev
->
query
,
qev
->
q_len
+
1
)
==
0
)
thd
->
options
&=
~
OPTION_BEGIN
;
}
break
;
case
XID_EVENT
:
DBUG_PRINT
(
"info"
,
(
"XID_EVENT"
));
thd
->
options
&=
~
OPTION_BEGIN
;
break
;
}
}
#endif
if
((
ev
->
server_id
==
(
uint32
)
::
server_id
&&
!
replicate_same_server_id
&&
type_code
!=
FORMAT_DESCRIPTION_EVENT
)
||
(
rli
->
slave_skip_counter
&&
type_code
!=
ROTATE_EVENT
&&
type_code
!=
STOP_EVENT
&&
type_code
!=
START_EVENT_V3
&&
type_code
!=
FORMAT_DESCRIPTION_EVENT
))
{
DBUG_PRINT
(
"info"
,
(
"event skipped"
));
if
(
thd
->
options
&
OPTION_BEGIN
)
rli
->
inc_event_relay_log_pos
();
else
{
rli
->
inc_group_relay_log_pos
((
type_code
==
ROTATE_EVENT
||
type_code
==
STOP_EVENT
||
type_code
==
FORMAT_DESCRIPTION_EVENT
)
?
LL
(
0
)
:
ev
->
log_pos
,
1
/* skip lock*/
);
flush_relay_log_info
(
rli
);
}
DBUG_PRINT
(
"info"
,
(
"thd->options: %s"
,
(
thd
->
options
&
OPTION_BEGIN
)
?
"OPTION_BEGIN"
:
""
));
/*
Protect against common user error of setting the counter to 1
instead of 2 while recovering from an insert which used auto_increment,
rand or user var.
*/
if
(
rli
->
slave_skip_counter
&&
!
((
type_code
==
INTVAR_EVENT
||
type_code
==
RAND_EVENT
||
type_code
==
USER_VAR_EVENT
)
&&
rli
->
slave_skip_counter
==
1
)
&&
#if MYSQL_VERSION_ID < 50100
/*
Decrease the slave skip counter only if we are not inside
a transaction or the slave skip counter is more than
1. The slave skip counter will be decreased from 1 to 0
when reaching the final ROLLBACK, COMMIT, or XID_EVENT.
*/
(
!
(
thd
->
options
&
OPTION_BEGIN
)
||
rli
->
slave_skip_counter
>
1
)
&&
#endif
/*
The events from ourselves which have something to do with the relay
log itself must be skipped, true, but they mustn't decrement
rli->slave_skip_counter, because the user is supposed to not see
these events (they are not in the master's binlog) and if we
decremented, START SLAVE would for example decrement when it sees
the Rotate, so the event which the user probably wanted to skip
would not be skipped.
*/
!
(
ev
->
server_id
==
(
uint32
)
::
server_id
&&
(
type_code
==
ROTATE_EVENT
||
type_code
==
STOP_EVENT
||
type_code
==
START_EVENT_V3
||
type_code
==
FORMAT_DESCRIPTION_EVENT
)))
--
rli
->
slave_skip_counter
;
pthread_mutex_unlock
(
&
rli
->
data_lock
);
delete
ev
;
return
0
;
// avoid infinite update loops
}
thd
->
server_id
=
ev
->
server_id
;
// use the original server id for logging
thd
->
server_id
=
ev
->
server_id
;
// use the original server id for logging
thd
->
set_time
();
// time the query
thd
->
set_time
();
// time the query
thd
->
lex
->
current_select
=
0
;
thd
->
lex
->
current_select
=
0
;
...
...
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