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
8d4bddef
Commit
8d4bddef
authored
Dec 21, 2006
by
mats@romeo.(none)
Browse files
Options
Browse Files
Download
Plain Diff
Merge romeo.(none):/home/bk/b22864-mysql-5.1-new-rpl
into romeo.(none):/home/bk/merge-b22864-myql-5.1-new-rpl
parents
4722743c
be9ffb12
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
563 additions
and
93 deletions
+563
-93
mysql-test/r/rpl_row_create_table.result
mysql-test/r/rpl_row_create_table.result
+190
-1
mysql-test/t/rpl_row_create_table-slave.opt
mysql-test/t/rpl_row_create_table-slave.opt
+1
-0
mysql-test/t/rpl_row_create_table.test
mysql-test/t/rpl_row_create_table.test
+117
-8
sql/log.cc
sql/log.cc
+129
-29
sql/log.h
sql/log.h
+2
-0
sql/log_event.h
sql/log_event.h
+9
-3
sql/mysql_priv.h
sql/mysql_priv.h
+33
-33
sql/slave.cc
sql/slave.cc
+5
-0
sql/sql_class.h
sql/sql_class.h
+2
-0
sql/sql_insert.cc
sql/sql_insert.cc
+75
-19
No files found.
mysql-test/r/rpl_row_create_table.result
View file @
8d4bddef
...
...
@@ -127,7 +127,7 @@ NULL 5 10
NULL 6 12
CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3;
ERROR 23000: Duplicate entry '2' for key 'b'
SHOW BINLOG EVENTS FROM 1
256
;
SHOW BINLOG EVENTS FROM 1
118
;
Log_name Pos Event_type Server_id End_log_pos Info
CREATE TABLE t7 (a INT, b INT UNIQUE);
INSERT INTO t7 SELECT a,b FROM tt3;
...
...
@@ -212,3 +212,192 @@ Create Table CREATE TABLE `t9` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9;
STOP SLAVE;
SET GLOBAL storage_engine=@storage_engine;
START SLAVE;
================ BUG#22864 ================
STOP SLAVE;
RESET SLAVE;
RESET MASTER;
START SLAVE;
SET AUTOCOMMIT=0;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
CREATE TABLE t2 ENGINE=INNODB SELECT * FROM t1;
ROLLBACK;
CREATE TABLE t3 ENGINE=INNODB SELECT * FROM t1;
INSERT INTO t3 VALUES (4),(5),(6);
ROLLBACK;
CREATE TABLE t4 ENGINE=INNODB SELECT * FROM t1;
INSERT INTO t1 VALUES (4),(5),(6);
ROLLBACK;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
SHOW TABLES;
Tables_in_test
t1
t2
t3
t4
SELECT TABLE_NAME,ENGINE
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 't_'
ORDER BY TABLE_NAME;
TABLE_NAME ENGINE
t1 MyISAM
t2 InnoDB
t3 InnoDB
t4 InnoDB
SELECT * FROM t1 ORDER BY a;
a
1
2
3
4
5
6
SELECT * FROM t2 ORDER BY a;
a
1
2
3
SELECT * FROM t3 ORDER BY a;
a
1
2
3
SELECT * FROM t4 ORDER BY a;
a
1
2
3
SHOW BINLOG EVENTS;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 4 Format_desc 1 102 Server ver: #, Binlog ver: #
master-bin.000001 102 Query 1 188 use `test`; CREATE TABLE t1 (a INT)
master-bin.000001 188 Table_map 1 227 table_id: # (test.t1)
master-bin.000001 227 Write_rows 1 271 table_id: # flags: STMT_END_F
master-bin.000001 271 Query 1 339 use `test`; BEGIN
master-bin.000001 339 Query 1 125 use `test`; CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB
master-bin.000001 464 Table_map 1 164 table_id: # (test.t2)
master-bin.000001 503 Write_rows 1 208 table_id: # flags: STMT_END_F
master-bin.000001 547 Xid 1 574 COMMIT /* XID */
master-bin.000001 574 Query 1 642 use `test`; BEGIN
master-bin.000001 642 Query 1 125 use `test`; CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB
master-bin.000001 767 Table_map 1 164 table_id: # (test.t3)
master-bin.000001 806 Write_rows 1 208 table_id: # flags: STMT_END_F
master-bin.000001 850 Xid 1 877 COMMIT /* XID */
master-bin.000001 877 Query 1 945 use `test`; BEGIN
master-bin.000001 945 Query 1 125 use `test`; CREATE TABLE `t4` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB
master-bin.000001 1070 Table_map 1 164 table_id: # (test.t4)
master-bin.000001 1109 Write_rows 1 208 table_id: # flags: STMT_END_F
master-bin.000001 1153 Xid 1 1180 COMMIT /* XID */
master-bin.000001 1180 Table_map 1 1219 table_id: # (test.t1)
master-bin.000001 1219 Write_rows 1 1263 table_id: # flags: STMT_END_F
SHOW TABLES;
Tables_in_test
t1
t2
t3
t4
SELECT TABLE_NAME,ENGINE
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 't_'
ORDER BY TABLE_NAME;
TABLE_NAME ENGINE
t1 MyISAM
t2 InnoDB
t3 InnoDB
t4 InnoDB
SELECT * FROM t1 ORDER BY a;
a
1
2
3
4
5
6
SELECT * FROM t2 ORDER BY a;
a
1
2
3
SELECT * FROM t3 ORDER BY a;
a
1
2
3
SELECT * FROM t4 ORDER BY a;
a
1
2
3
DROP TABLE IF EXISTS t1,t2,t3,t4;
SET AUTOCOMMIT=1;
STOP SLAVE;
RESET SLAVE;
RESET MASTER;
START SLAVE;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
CREATE TABLE t2 (a INT) ENGINE=INNODB;
BEGIN;
INSERT INTO t2 SELECT a*a FROM t1;
CREATE TEMPORARY TABLE tt1
SELECT a+1 AS a
FROM t1
WHERE a MOD 2 = 1;
INSERT INTO t2 SELECT a+2 FROM tt1;
COMMIT;
SELECT * FROM t2 ORDER BY a;
a
1
4
4
6
9
SHOW BINLOG EVENTS;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 4 Format_desc 1 102 Server ver: #, Binlog ver: #
master-bin.000001 102 Query 1 188 use `test`; CREATE TABLE t1 (a INT)
master-bin.000001 188 Table_map 1 227 table_id: # (test.t1)
master-bin.000001 227 Write_rows 1 271 table_id: # flags: STMT_END_F
master-bin.000001 271 Query 1 371 use `test`; CREATE TABLE t2 (a INT) ENGINE=INNODB
master-bin.000001 371 Query 1 439 use `test`; BEGIN
master-bin.000001 439 Table_map 1 39 table_id: # (test.t2)
master-bin.000001 478 Write_rows 1 83 table_id: # flags: STMT_END_F
master-bin.000001 522 Table_map 1 122 table_id: # (test.t2)
master-bin.000001 561 Write_rows 1 161 table_id: # flags: STMT_END_F
master-bin.000001 600 Xid 1 627 COMMIT /* XID */
SELECT * FROM t2 ORDER BY a;
a
1
4
4
6
9
TRUNCATE TABLE t2;
BEGIN;
INSERT INTO t2 SELECT a*a FROM t1;
CREATE TEMPORARY TABLE tt2
SELECT a+1 AS a
FROM t1
WHERE a MOD 2 = 1;
INSERT INTO t2 SELECT a+2 FROM tt2;
ROLLBACK;
SELECT * FROM t2 ORDER BY a;
a
SHOW BINLOG EVENTS FROM 627;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 627 Query 1 80 use `test`; TRUNCATE TABLE t2
master-bin.000001 707 Xid 1 734 COMMIT /* XID */
SELECT * FROM t2 ORDER BY a;
a
DROP TABLE t1,t2;
mysql-test/t/rpl_row_create_table-slave.opt
0 → 100644
View file @
8d4bddef
--innodb
mysql-test/t/rpl_row_create_table.test
View file @
8d4bddef
...
...
@@ -2,6 +2,10 @@
--
source
include
/
have_binlog_format_row
.
inc
--
source
include
/
master
-
slave
.
inc
--
source
include
/
have_innodb
.
inc
connection
slave
;
--
source
include
/
have_innodb
.
inc
connection
master
;
# Bug#18326: Do not lock table for writing during prepare of statement
# The use of the ps protocol causes extra table maps in the binlog, so
...
...
@@ -31,7 +35,7 @@ CREATE TABLE t2 (a INT, b INT) ENGINE=Merge;
CREATE
TABLE
t3
(
a
INT
,
b
INT
)
CHARSET
=
utf8
;
CREATE
TABLE
t4
(
a
INT
,
b
INT
)
ENGINE
=
Merge
CHARSET
=
utf8
;
--
replace_column
1
# 4 # 5 #
--
replace_regex
/
table_id
:
[
0
-
9
]
+/
table_id
:
#/
--
replace_regex
/
\
/
\
*
xid
=.*
\
*
\
//\/* XID *\// /
table_id: [0-9]+/table_id: #/
--
query_vertical
SHOW
BINLOG
EVENTS
FROM
212
--
echo
****
On
Master
****
--
query_vertical
SHOW
CREATE
TABLE
t1
...
...
@@ -66,8 +70,8 @@ connection master;
--
error
1062
CREATE
TABLE
t7
(
UNIQUE
(
b
))
SELECT
a
,
b
FROM
tt3
;
# Shouldn't be written to the binary log
--
replace_regex
/
table_id
:
[
0
-
9
]
+/
table_id
:
#/
SHOW
BINLOG
EVENTS
FROM
1
256
;
--
replace_regex
/
\
/
\
*
xid
=.*
\
*
\
//\/* XID *\// /
table_id: [0-9]+/table_id: #/
SHOW
BINLOG
EVENTS
FROM
1
118
;
# Test that INSERT-SELECT works the same way as for SBR.
CREATE
TABLE
t7
(
a
INT
,
b
INT
UNIQUE
);
...
...
@@ -75,7 +79,7 @@ CREATE TABLE t7 (a INT, b INT UNIQUE);
INSERT
INTO
t7
SELECT
a
,
b
FROM
tt3
;
SELECT
*
FROM
t7
ORDER
BY
a
,
b
;
# Should be written to the binary log
--
replace_regex
/
table_id
:
[
0
-
9
]
+/
table_id
:
#/
--
replace_regex
/
\
/
\
*
xid
=.*
\
*
\
//\/* XID *\// /
table_id: [0-9]+/table_id: #/
SHOW
BINLOG
EVENTS
FROM
1118
;
sync_slave_with_master
;
SELECT
*
FROM
t7
ORDER
BY
a
,
b
;
...
...
@@ -86,7 +90,7 @@ INSERT INTO tt4 VALUES (4,8), (5,10), (6,12);
BEGIN
;
INSERT
INTO
t7
SELECT
a
,
b
FROM
tt4
;
ROLLBACK
;
--
replace_regex
/
table_id
:
[
0
-
9
]
+/
table_id
:
#/
--
replace_regex
/
\
/
\
*
xid
=.*
\
*
\
//\/* XID *\// /
table_id: [0-9]+/table_id: #/
SHOW
BINLOG
EVENTS
FROM
1314
;
SELECT
*
FROM
t7
ORDER
BY
a
,
b
;
sync_slave_with_master
;
...
...
@@ -101,7 +105,7 @@ CREATE TEMPORARY TABLE tt7 SELECT 1;
--
echo
****
On
Master
****
--
query_vertical
SHOW
CREATE
TABLE
t8
--
query_vertical
SHOW
CREATE
TABLE
t9
--
replace_regex
/
table_id
:
[
0
-
9
]
+/
table_id
:
#/
--
replace_regex
/
\
/
\
*
xid
=.*
\
*
\
//\/* XID *\// /
table_id: [0-9]+/table_id: #/
SHOW
BINLOG
EVENTS
FROM
1410
;
sync_slave_with_master
;
--
echo
****
On
Slave
****
...
...
@@ -109,12 +113,117 @@ sync_slave_with_master;
--
query_vertical
SHOW
CREATE
TABLE
t9
connection
master
;
--
disable_query_log
DROP
TABLE
IF
EXISTS
t1
,
t2
,
t3
,
t4
,
t5
,
t6
,
t7
,
t8
,
t9
;
sync_slave_with_master
;
# Here we reset the value of the default storage engine
STOP
SLAVE
;
SET
GLOBAL
storage_engine
=@
storage_engine
;
START
SLAVE
;
--
enable_query_log
--
enable_ps_protocol
# BUG#22864 (Rollback following CREATE ... SELECT discards 'CREATE
# table' from log):
--
echo
================
BUG
#22864 ================
connection
slave
;
STOP
SLAVE
;
RESET
SLAVE
;
connection
master
;
RESET
MASTER
;
connection
slave
;
START
SLAVE
;
connection
master
;
SET
AUTOCOMMIT
=
0
;
CREATE
TABLE
t1
(
a
INT
);
INSERT
INTO
t1
VALUES
(
1
),(
2
),(
3
);
CREATE
TABLE
t2
ENGINE
=
INNODB
SELECT
*
FROM
t1
;
ROLLBACK
;
CREATE
TABLE
t3
ENGINE
=
INNODB
SELECT
*
FROM
t1
;
INSERT
INTO
t3
VALUES
(
4
),(
5
),(
6
);
ROLLBACK
;
CREATE
TABLE
t4
ENGINE
=
INNODB
SELECT
*
FROM
t1
;
INSERT
INTO
t1
VALUES
(
4
),(
5
),(
6
);
ROLLBACK
;
SHOW
TABLES
;
SELECT
TABLE_NAME
,
ENGINE
FROM
INFORMATION_SCHEMA
.
TABLES
WHERE
TABLE_NAME
LIKE
't_'
ORDER
BY
TABLE_NAME
;
SELECT
*
FROM
t1
ORDER
BY
a
;
SELECT
*
FROM
t2
ORDER
BY
a
;
SELECT
*
FROM
t3
ORDER
BY
a
;
SELECT
*
FROM
t4
ORDER
BY
a
;
--
replace_regex
/
\
/
\
*
xid
=.*
\
*
\
//\/* XID *\// /Server ver: .*, Binlog ver: .*/Server ver: #, Binlog ver: #/ /table_id: [0-9]+/table_id: #/
SHOW
BINLOG
EVENTS
;
sync_slave_with_master
;
SHOW
TABLES
;
SELECT
TABLE_NAME
,
ENGINE
FROM
INFORMATION_SCHEMA
.
TABLES
WHERE
TABLE_NAME
LIKE
't_'
ORDER
BY
TABLE_NAME
;
SELECT
*
FROM
t1
ORDER
BY
a
;
SELECT
*
FROM
t2
ORDER
BY
a
;
SELECT
*
FROM
t3
ORDER
BY
a
;
SELECT
*
FROM
t4
ORDER
BY
a
;
connection
master
;
DROP
TABLE
IF
EXISTS
t1
,
t2
,
t3
,
t4
;
SET
AUTOCOMMIT
=
1
;
sync_slave_with_master
;
# Some tests with temporary tables
connection
slave
;
STOP
SLAVE
;
RESET
SLAVE
;
connection
master
;
RESET
MASTER
;
connection
slave
;
START
SLAVE
;
connection
master
;
CREATE
TABLE
t1
(
a
INT
);
INSERT
INTO
t1
VALUES
(
1
),(
2
),(
3
);
CREATE
TABLE
t2
(
a
INT
)
ENGINE
=
INNODB
;
BEGIN
;
INSERT
INTO
t2
SELECT
a
*
a
FROM
t1
;
CREATE
TEMPORARY
TABLE
tt1
SELECT
a
+
1
AS
a
FROM
t1
WHERE
a
MOD
2
=
1
;
INSERT
INTO
t2
SELECT
a
+
2
FROM
tt1
;
COMMIT
;
SELECT
*
FROM
t2
ORDER
BY
a
;
--
replace_regex
/
\
/
\
*
xid
=.*
\
*
\
//\/* XID *\// /Server ver: .*, Binlog ver: .*/Server ver: #, Binlog ver: #/ /table_id: [0-9]+/table_id: #/
SHOW
BINLOG
EVENTS
;
sync_slave_with_master
;
SELECT
*
FROM
t2
ORDER
BY
a
;
connection
master
;
TRUNCATE
TABLE
t2
;
BEGIN
;
INSERT
INTO
t2
SELECT
a
*
a
FROM
t1
;
CREATE
TEMPORARY
TABLE
tt2
SELECT
a
+
1
AS
a
FROM
t1
WHERE
a
MOD
2
=
1
;
INSERT
INTO
t2
SELECT
a
+
2
FROM
tt2
;
ROLLBACK
;
SELECT
*
FROM
t2
ORDER
BY
a
;
--
replace_regex
/
\
/
\
*
xid
=.*
\
*
\
//\/* XID *\// /Server ver: .*, Binlog ver: .*/Server ver: #, Binlog ver: #/ /table_id: [0-9]+/table_id: #/
SHOW
BINLOG
EVENTS
FROM
627
;
sync_slave_with_master
;
SELECT
*
FROM
t2
ORDER
BY
a
;
connection
master
;
DROP
TABLE
t1
,
t2
;
sync_slave_with_master
;
sql/log.cc
View file @
8d4bddef
...
...
@@ -81,6 +81,41 @@ char *make_default_log_name(char *buff,const char* log_ext)
MYF
(
MY_UNPACK_FILENAME
|
MY_APPEND_EXT
));
}
/*
Helper class to hold a mutex for the duration of the
block.
Eliminates the need for explicit unlocking of mutexes on, e.g.,
error returns. On passing a null pointer, the sentry will not do
anything.
*/
class
Mutex_sentry
{
public:
Mutex_sentry
(
pthread_mutex_t
*
mutex
)
:
m_mutex
(
mutex
)
{
if
(
m_mutex
)
pthread_mutex_lock
(
mutex
);
}
~
Mutex_sentry
()
{
if
(
m_mutex
)
pthread_mutex_unlock
(
m_mutex
);
#ifndef DBUG_OFF
m_mutex
=
0
;
#endif
}
private:
pthread_mutex_t
*
m_mutex
;
// It's not allowed to copy this object in any way
Mutex_sentry
(
Mutex_sentry
const
&
);
void
operator
=
(
Mutex_sentry
const
&
);
};
/*
Helper class to store binary log transaction data.
*/
...
...
@@ -113,9 +148,15 @@ public:
*/
void
truncate
(
my_off_t
pos
)
{
#ifdef HAVE_ROW_BASED_REPLICATION
DBUG_PRINT
(
"info"
,
(
"truncating to position %lu"
,
pos
));
DBUG_PRINT
(
"info"
,
(
"before_stmt_pos=%lu"
,
pos
));
delete
pending
();
set_pending
(
0
);
reinit_io_cache
(
&
trans_log
,
WRITE_CACHE
,
pos
,
0
,
0
);
if
(
pos
<
before_stmt_pos
)
before_stmt_pos
=
MY_OFF_T_UNDEF
;
#endif
}
/*
...
...
@@ -1483,12 +1524,11 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
If rolling back a statement in a transaction, we truncate the
transaction cache to remove the statement.
*/
if
(
all
||
!
(
thd
->
options
&
(
OPTION_BEGIN
|
OPTION_NOT_AUTOCOMMIT
)))
trx_data
->
reset
();
else
trx_data
->
truncate
(
trx_data
->
before_stmt_pos
);
// ...statement
else
// ...statement
trx_data
->
truncate
(
trx_data
->
before_stmt_pos
);
/*
We need to step the table map version on a rollback to ensure
...
...
@@ -3415,6 +3455,18 @@ THD::binlog_start_trans_and_stmt()
if
(
trx_data
==
NULL
||
trx_data
->
before_stmt_pos
==
MY_OFF_T_UNDEF
)
{
this
->
binlog_set_stmt_begin
();
if
(
options
&
(
OPTION_NOT_AUTOCOMMIT
|
OPTION_BEGIN
))
trans_register_ha
(
this
,
TRUE
,
binlog_hton
);
trans_register_ha
(
this
,
FALSE
,
binlog_hton
);
}
DBUG_VOID_RETURN
;
}
void
THD
::
binlog_set_stmt_begin
()
{
binlog_trx_data
*
trx_data
=
(
binlog_trx_data
*
)
ha_data
[
binlog_hton
->
slot
];
/*
The call to binlog_trans_log_savepos() might create the trx_data
structure, if it didn't exist before, so we save the position
...
...
@@ -3424,16 +3476,38 @@ THD::binlog_start_trans_and_stmt()
my_off_t
pos
=
0
;
binlog_trans_log_savepos
(
this
,
&
pos
);
trx_data
=
(
binlog_trx_data
*
)
ha_data
[
binlog_hton
->
slot
];
trx_data
->
before_stmt_pos
=
pos
;
}
if
(
options
&
(
OPTION_NOT_AUTOCOMMIT
|
OPTION_BEGIN
))
trans_register_ha
(
this
,
TRUE
,
binlog_hton
);
trans_register_ha
(
this
,
FALSE
,
binlog_hton
);
int
THD
::
binlog_flush_transaction_cache
()
{
DBUG_ENTER
(
"binlog_flush_transaction_cache"
);
binlog_trx_data
*
trx_data
=
(
binlog_trx_data
*
)
ha_data
[
binlog_hton
->
slot
];
DBUG_PRINT
(
"enter"
,
(
"trx_data=0x%lu"
,
trx_data
));
if
(
trx_data
)
DBUG_PRINT
(
"enter"
,
(
"trx_data->before_stmt_pos=%u"
,
trx_data
->
before_stmt_pos
));
/*
Write the transaction cache to the binary log. We don't flush and
sync the log file since we don't know if more will be written to
it. If the caller want the log file sync:ed, the caller has to do
it.
The transaction data is only reset upon a successful write of the
cache to the binary log.
*/
if
(
trx_data
&&
likely
(
mysql_bin_log
.
is_open
()))
{
if
(
int
error
=
mysql_bin_log
.
write_cache
(
&
trx_data
->
trans_log
,
true
,
true
))
DBUG_RETURN
(
error
);
trx_data
->
reset
();
}
DBUG_VOID_RETURN
;
DBUG_RETURN
(
0
);
}
/*
Write a table map to the binary log.
*/
...
...
@@ -3843,6 +3917,40 @@ uint MYSQL_BIN_LOG::next_file_id()
}
/*
Write the contents of a cache to the binary log.
SYNOPSIS
write_cache()
cache Cache to write to the binary log
lock_log True if the LOCK_log mutex should be aquired, false otherwise
sync_log True if the log should be flushed and sync:ed
DESCRIPTION
Write the contents of the cache to the binary log. The cache will
be reset as a READ_CACHE to be able to read the contents from it.
*/
int
MYSQL_BIN_LOG
::
write_cache
(
IO_CACHE
*
cache
,
bool
lock_log
,
bool
sync_log
)
{
Mutex_sentry
sentry
(
lock_log
?
&
LOCK_log
:
NULL
);
if
(
reinit_io_cache
(
cache
,
READ_CACHE
,
0
,
0
,
0
))
return
ER_ERROR_ON_WRITE
;
uint
bytes
=
my_b_bytes_in_cache
(
cache
);
do
{
if
(
my_b_write
(
&
log_file
,
cache
->
read_pos
,
bytes
))
return
ER_ERROR_ON_WRITE
;
cache
->
read_pos
=
cache
->
read_end
;
}
while
((
bytes
=
my_b_fill
(
cache
)));
if
(
sync_log
)
flush_and_sync
();
return
0
;
// All OK
}
/*
Write a cached log entry to the binary log
...
...
@@ -3850,6 +3958,8 @@ uint MYSQL_BIN_LOG::next_file_id()
write()
thd
cache The cache to copy to the binlog
commit_event The commit event to print after writing the
contents of the cache.
NOTE
- We only come here if there is something in the cache.
...
...
@@ -3909,19 +4019,9 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
if
(
qinfo
.
write
(
&
log_file
))
goto
err
;
}
/* Read from the file used to cache the queries .*/
if
(
reinit_io_cache
(
cache
,
READ_CACHE
,
0
,
0
,
0
))
goto
err
;
length
=
my_b_bytes_in_cache
(
cache
);
DBUG_EXECUTE_IF
(
"half_binlogged_transaction"
,
length
-=
100
;);
do
{
/* Write data to the binary log file */
if
(
my_b_write
(
&
log_file
,
cache
->
read_pos
,
length
))
if
((
write_error
=
write_cache
(
cache
,
false
,
false
)))
goto
err
;
cache
->
read_pos
=
cache
->
read_end
;
// Mark buffer used up
DBUG_EXECUTE_IF
(
"half_binlogged_transaction"
,
goto
DBUG_skip_commit
;);
}
while
((
length
=
my_b_fill
(
cache
)));
if
(
commit_event
&&
commit_event
->
write
(
&
log_file
))
goto
err
;
...
...
sql/log.h
View file @
8d4bddef
...
...
@@ -340,6 +340,8 @@ public:
bool
write
(
Log_event
*
event_info
);
// binary log write
bool
write
(
THD
*
thd
,
IO_CACHE
*
cache
,
Log_event
*
commit_event
);
int
write_cache
(
IO_CACHE
*
cache
,
bool
lock_log
,
bool
flush_and_sync
);
void
start_union_events
(
THD
*
thd
);
void
stop_union_events
(
THD
*
thd
);
bool
is_query_in_union
(
THD
*
thd
,
query_id_t
query_id_param
);
...
...
sql/log_event.h
View file @
8d4bddef
...
...
@@ -425,12 +425,18 @@ struct sql_ex_info
either, as the manual says (because a too big in-memory temp table is
automatically written to disk).
*/
#define OPTIONS_WRITTEN_TO_BIN_LOG (OPTION_AUTO_IS_NULL | \
OPTION_NO_FOREIGN_KEY_CHECKS | OPTION_RELAXED_UNIQUE_CHECKS)
#define OPTIONS_WRITTEN_TO_BIN_LOG \
(OPTION_AUTO_IS_NULL | OPTION_NO_FOREIGN_KEY_CHECKS | \
OPTION_RELAXED_UNIQUE_CHECKS | OPTION_NOT_AUTOCOMMIT)
#if OPTIONS_WRITTEN_TO_BIN_LOG != ((1L << 14) | (1L << 26) | (1L << 27))
/* Shouldn't be defined before */
#define EXPECTED_OPTIONS \
((ULL(1) << 14) | (ULL(1) << 26) | (ULL(1) << 27) | (ULL(1) << 19))
#if OPTIONS_WRITTEN_TO_BIN_LOG != EXPECTED_OPTIONS
#error OPTIONS_WRITTEN_TO_BIN_LOG must NOT change their values!
#endif
#undef EXPECTED_OPTIONS
/* You shouldn't use this one */
enum
Log_event_type
{
...
...
sql/mysql_priv.h
View file @
8d4bddef
...
...
@@ -307,54 +307,54 @@ MY_LOCALE *my_locale_by_number(uint number);
TODO: separate three contexts above, move them to separate bitfields.
*/
#define SELECT_DISTINCT
(
LL(1) << 0) // SELECT, user
#define SELECT_STRAIGHT_JOIN
(
LL(1) << 1) // SELECT, user
#define SELECT_DESCRIBE
(
LL(1) << 2) // SELECT, user
#define SELECT_SMALL_RESULT
(
LL(1) << 3) // SELECT, user
#define SELECT_BIG_RESULT
(
LL(1) << 4) // SELECT, user
#define OPTION_FOUND_ROWS
(
LL(1) << 5) // SELECT, user
#define OPTION_TO_QUERY_CACHE
(
LL(1) << 6) // SELECT, user
#define SELECT_NO_JOIN_CACHE
(
LL(1) << 7) // intern
#define OPTION_BIG_TABLES
(
LL(1) << 8) // THD, user
#define OPTION_BIG_SELECTS
(
LL(1) << 9) // THD, user
#define OPTION_LOG_OFF
(
LL(1) << 10) // THD, user
#define OPTION_QUOTE_SHOW_CREATE (
LL(1) << 11)
// THD, user
#define TMP_TABLE_ALL_COLUMNS
(
LL(1) << 12) // SELECT, intern
#define OPTION_WARNINGS
(
LL(1) << 13) // THD, user
#define OPTION_AUTO_IS_NULL
(
LL(1) << 14) // THD, user, binlog
#define OPTION_FOUND_COMMENT
(
LL(1) << 15) // SELECT, intern, parser
#define OPTION_SAFE_UPDATES
(
LL(1) << 16) // THD, user
#define OPTION_BUFFER_RESULT
(
LL(1) << 17) // SELECT, user
#define OPTION_BIN_LOG
(
LL(1) << 18) // THD, user
#define OPTION_NOT_AUTOCOMMIT
(
LL(1) << 19) // THD, user
#define OPTION_BEGIN
(
LL(1) << 20) // THD, intern
#define OPTION_TABLE_LOCK
(
LL(1) << 21) // THD, intern
#define OPTION_QUICK
(
LL(1) << 22) // SELECT (for DELETE)
#define OPTION_KEEP_LOG
(
LL(1) << 23) // Keep binlog on rollback
#define SELECT_DISTINCT
(U
LL(1) << 0) // SELECT, user
#define SELECT_STRAIGHT_JOIN
(U
LL(1) << 1) // SELECT, user
#define SELECT_DESCRIBE
(U
LL(1) << 2) // SELECT, user
#define SELECT_SMALL_RESULT
(U
LL(1) << 3) // SELECT, user
#define SELECT_BIG_RESULT
(U
LL(1) << 4) // SELECT, user
#define OPTION_FOUND_ROWS
(U
LL(1) << 5) // SELECT, user
#define OPTION_TO_QUERY_CACHE
(U
LL(1) << 6) // SELECT, user
#define SELECT_NO_JOIN_CACHE
(U
LL(1) << 7) // intern
#define OPTION_BIG_TABLES
(U
LL(1) << 8) // THD, user
#define OPTION_BIG_SELECTS
(U
LL(1) << 9) // THD, user
#define OPTION_LOG_OFF
(U
LL(1) << 10) // THD, user
#define OPTION_QUOTE_SHOW_CREATE (
ULL(1) << 11)
// THD, user
#define TMP_TABLE_ALL_COLUMNS
(U
LL(1) << 12) // SELECT, intern
#define OPTION_WARNINGS
(U
LL(1) << 13) // THD, user
#define OPTION_AUTO_IS_NULL
(U
LL(1) << 14) // THD, user, binlog
#define OPTION_FOUND_COMMENT
(U
LL(1) << 15) // SELECT, intern, parser
#define OPTION_SAFE_UPDATES
(U
LL(1) << 16) // THD, user
#define OPTION_BUFFER_RESULT
(U
LL(1) << 17) // SELECT, user
#define OPTION_BIN_LOG
(U
LL(1) << 18) // THD, user
#define OPTION_NOT_AUTOCOMMIT
(U
LL(1) << 19) // THD, user
#define OPTION_BEGIN
(U
LL(1) << 20) // THD, intern
#define OPTION_TABLE_LOCK
(U
LL(1) << 21) // THD, intern
#define OPTION_QUICK
(U
LL(1) << 22) // SELECT (for DELETE)
#define OPTION_KEEP_LOG
(U
LL(1) << 23) // Keep binlog on rollback
/* The following is used to detect a conflict with DISTINCT */
#define SELECT_ALL
(
LL(1) << 24) // SELECT, user, parser
#define SELECT_ALL
(U
LL(1) << 24) // SELECT, user, parser
/* Set if we are updating a non-transaction safe table */
#define OPTION_STATUS_NO_TRANS_UPDATE (LL(1) << 25) // THD, intern
#define OPTION_STATUS_NO_TRANS_UPDATE (
U
LL(1) << 25) // THD, intern
/* The following can be set when importing tables in a 'wrong order'
to suppress foreign key checks */
#define OPTION_NO_FOREIGN_KEY_CHECKS (LL(1) << 26) // THD, user, binlog
#define OPTION_NO_FOREIGN_KEY_CHECKS (
U
LL(1) << 26) // THD, user, binlog
/* The following speeds up inserts to InnoDB tables by suppressing unique
key checks in some cases */
#define OPTION_RELAXED_UNIQUE_CHECKS (LL(1) << 27) // THD, user, binlog
#define SELECT_NO_UNLOCK (LL(1) << 28) // SELECT, intern
#define OPTION_SCHEMA_TABLE (LL(1) << 29) // SELECT, intern
#define OPTION_RELAXED_UNIQUE_CHECKS (
U
LL(1) << 27) // THD, user, binlog
#define SELECT_NO_UNLOCK (
U
LL(1) << 28) // SELECT, intern
#define OPTION_SCHEMA_TABLE (
U
LL(1) << 29) // SELECT, intern
/* Flag set if setup_tables already done */
#define OPTION_SETUP_TABLES_DONE (LL(1) << 30) // intern
#define OPTION_SETUP_TABLES_DONE (
U
LL(1) << 30) // intern
/* If not set then the thread will ignore all warnings with level notes. */
#define OPTION_SQL_NOTES (LL(1) << 31) // THD, user
#define OPTION_SQL_NOTES (
U
LL(1) << 31) // THD, user
/*
Force the used temporary table to be a MyISAM table (because we will use
fulltext functions when reading from it.
*/
#define TMP_TABLE_FORCE_MYISAM (LL(1) << 32)
#define TMP_TABLE_FORCE_MYISAM (
U
LL(1) << 32)
/*
Maximum length of time zone name that we support
...
...
sql/slave.cc
View file @
8d4bddef
...
...
@@ -33,6 +33,7 @@
int
queue_event
(
MASTER_INFO
*
mi
,
const
char
*
buf
,
ulong
event_len
);
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
#define MAX_SLAVE_RETRY_PAUSE 5
bool
use_slave_mask
=
0
;
...
...
@@ -1799,6 +1800,10 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
if
(
!
ev
->
when
)
ev
->
when
=
time
(
NULL
);
ev
->
thd
=
thd
;
// because up to this point, ev->thd == 0
DBUG_PRINT
(
"info"
,
(
"thd->options={ %s%s}"
,
FLAGSTR
(
thd
->
options
,
OPTION_NOT_AUTOCOMMIT
),
FLAGSTR
(
thd
->
options
,
OPTION_BEGIN
)));
exec_res
=
ev
->
exec_event
(
rli
);
DBUG_PRINT
(
"info"
,
(
"exec_event result: %d"
,
exec_res
));
DBUG_ASSERT
(
rli
->
sql_thd
==
thd
);
...
...
sql/sql_class.h
View file @
8d4bddef
...
...
@@ -946,6 +946,8 @@ public:
Public interface to write RBR events to the binlog
*/
void
binlog_start_trans_and_stmt
();
int
binlog_flush_transaction_cache
();
void
binlog_set_stmt_begin
();
int
binlog_write_table_map
(
TABLE
*
table
,
bool
is_transactional
);
int
binlog_write_row
(
TABLE
*
table
,
bool
is_transactional
,
MY_BITMAP
const
*
cols
,
my_size_t
colcnt
,
...
...
sql/sql_insert.cc
View file @
8d4bddef
...
...
@@ -2646,8 +2646,7 @@ void select_insert::send_error(uint errcode,const char *err)
If the creation of the table failed (due to a syntax error, for
example), no table will have been opened and therefore 'table'
will be NULL. In that case, we still need to execute the rollback
and the end of the function to truncate the binary log, but we can
skip all the intermediate steps.
and the end of the function.
*/
if
(
table
)
{
...
...
@@ -2678,10 +2677,8 @@ void select_insert::send_error(uint errcode,const char *err)
if
(
!
table
->
file
->
has_transactions
())
{
if
(
mysql_bin_log
.
is_open
())
{
thd
->
binlog_query
(
THD
::
ROW_QUERY_TYPE
,
thd
->
query
,
thd
->
query_length
,
table
->
file
->
has_transactions
(),
FALSE
);
}
if
(
!
thd
->
current_stmt_binlog_row_based
&&
!
table
->
s
->
tmp_table
&&
!
can_rollback_data
())
thd
->
options
|=
OPTION_STATUS_NO_TRANS_UPDATE
;
...
...
@@ -2948,6 +2945,24 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
DBUG_ENTER
(
"select_create::prepare"
);
TABLEOP_HOOKS
*
hook_ptr
=
NULL
;
/*
For row-based replication, the CREATE-SELECT statement is written
in two pieces: the first one contain the CREATE TABLE statement
necessary to create the table and the second part contain the rows
that should go into the table.
For non-temporary tables, the start of the CREATE-SELECT
implicitly commits the previous transaction, and all events
forming the statement will be stored the transaction cache. At end
of the statement, the entire statement is committed as a
transaction, and all events are written to the binary log.
On the master, the table is locked for the duration of the
statement, but since the CREATE part is replicated as a simple
statement, there is no way to lock the table for accesses on the
slave. Hence, we have to hold on to the CREATE part of the
statement until the statement has finished.
*/
class
MY_HOOKS
:
public
TABLEOP_HOOKS
{
public:
MY_HOOKS
(
select_create
*
x
)
:
ptr
(
x
)
{
}
...
...
@@ -2957,7 +2972,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
TABLE
const
*
const
table
=
*
tables
;
if
(
ptr
->
get_thd
()
->
current_stmt_binlog_row_based
&&
table
->
s
->
tmp_table
==
NO_TMP_TABLE
&&
!
table
->
s
->
tmp_table
&&
!
ptr
->
get_create_info
()
->
table_existed
)
{
ptr
->
binlog_show_create_table
(
tables
,
count
);
...
...
@@ -2973,9 +2988,9 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
unit
=
u
;
/*
Start a statement transaction before the create if we are
creat
ing
a non-temporary table and are using row-based replication for the
statement
.
Start a statement transaction before the create if we are
us
ing
row-based replication for the statement. If we are creating a
temporary table, we need to start a statement transaction
.
*/
if
((
thd
->
lex
->
create_info
.
options
&
HA_LEX_CREATE_TMP_TABLE
)
==
0
&&
thd
->
current_stmt_binlog_row_based
)
...
...
@@ -3075,13 +3090,35 @@ void select_create::store_values(List<Item> &values)
void
select_create
::
send_error
(
uint
errcode
,
const
char
*
err
)
{
DBUG_ENTER
(
"select_create::send_error"
);
DBUG_PRINT
(
"info"
,
(
"Current statement %s row-based"
,
thd
->
current_stmt_binlog_row_based
?
"is"
:
"is NOT"
));
DBUG_PRINT
(
"info"
,
(
"Current table (at 0x%lu) %s a temporary (or non-existant) table"
,
table
,
table
&&
!
table
->
s
->
tmp_table
?
"is NOT"
:
"is"
));
DBUG_PRINT
(
"info"
,
(
"Table %s prior to executing this statement"
,
get_create_info
()
->
table_existed
?
"existed"
:
"did not exist"
));
/*
Disable binlog, because we "roll back" partial inserts in ::abort
by removing the table, even for non-transactional tables.
This will execute any rollbacks that are necessary before writing
the transcation cache.
We disable the binary log since nothing should be written to the
binary log. This disabling is important, since we potentially do
a "roll back" of non-transactional tables by removing the table,
and the actual rollback might generate events that should not be
written to the binary log.
*/
tmp_disable_binlog
(
thd
);
select_insert
::
send_error
(
errcode
,
err
);
reenable_binlog
(
thd
);
DBUG_VOID_RETURN
;
}
...
...
@@ -3092,6 +3129,14 @@ bool select_create::send_eof()
abort
();
else
{
/*
Do an implicit commit at end of statement for non-temporary
tables. This can fail, but we should unlock the table
nevertheless.
*/
if
(
!
table
->
s
->
tmp_table
)
ha_commit
(
thd
);
// Can fail, but we proceed anyway
table
->
file
->
extra
(
HA_EXTRA_NO_IGNORE_DUP_KEY
);
table
->
file
->
extra
(
HA_EXTRA_WRITE_CANNOT_REPLACE
);
VOID
(
pthread_mutex_lock
(
&
LOCK_open
));
...
...
@@ -3110,12 +3155,31 @@ bool select_create::send_eof()
void
select_create
::
abort
()
{
DBUG_ENTER
(
"select_create::abort"
);
VOID
(
pthread_mutex_lock
(
&
LOCK_open
));
/*
We roll back the statement, including truncating the transaction
cache of the binary log, if the statement failed.
We roll back the statement prior to deleting the table and prior
to releasing the lock on the table, since there might be potential
for failure if the rollback is executed after the drop or after
unlocking the table.
We also roll back the statement regardless of whether the creation
of the table succeeded or not, since we need to reset the binary
log state.
*/
if
(
thd
->
current_stmt_binlog_row_based
)
ha_rollback_stmt
(
thd
);
if
(
thd
->
extra_lock
)
{
mysql_unlock_tables
(
thd
,
thd
->
extra_lock
);
thd
->
extra_lock
=
0
;
}
if
(
table
)
{
table
->
file
->
extra
(
HA_EXTRA_NO_IGNORE_DUP_KEY
);
...
...
@@ -3127,17 +3191,8 @@ void select_create::abort()
table
->
s
->
version
=
0
;
hash_delete
(
&
open_cache
,(
byte
*
)
table
);
if
(
!
create_info
->
table_existed
)
{
quick_rm_table
(
table_type
,
create_table
->
db
,
create_table
->
table_name
,
0
);
/*
We roll back the statement, including truncating the
transaction cache of the binary log, if the statement
failed.
*/
if
(
thd
->
current_stmt_binlog_row_based
)
ha_rollback_stmt
(
thd
);
}
/* Tell threads waiting for refresh that something has happened */
if
(
version
!=
refresh_version
)
broadcast_refresh
();
...
...
@@ -3147,6 +3202,7 @@ void select_create::abort()
table
=
0
;
// Safety
}
VOID
(
pthread_mutex_unlock
(
&
LOCK_open
));
DBUG_VOID_RETURN
;
}
...
...
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