mirror of
https://github.com/MariaDB/server.git
synced 2025-08-11 09:43:05 +03:00
Clean up and speed up interfaces for binary row logging
MDEV-21605 Clean up and speed up interfaces for binary row logging MDEV-21617 Bug fix for previous version of this code The intention is to have as few 'if' as possible in ha_write() and related functions. This is done by pre-calculating once per statement the row_logging state for all tables. Benefits are simpler and faster code both when binary logging is disabled and when it's enabled. Changes: - Added handler->row_logging to make it easy to check it table should be row logged. This also made it easier to disabling row logging for system, internal and temporary tables. - The tables row_logging capabilities are checked once per "statements that updates tables" in THD::binlog_prepare_for_row_logging() which is called when needed from THD::decide_logging_format(). - Removed most usage of tmp_disable_binlog(), reenable_binlog() and temporary saving and setting of thd->variables.option_bits. - Moved checks that can't change during a statement from check_table_binlog_row_based() to check_table_binlog_row_based_internal() - Removed flag row_already_logged (used by sequence engine) - Moved binlog_log_row() to a handler:: - Moved write_locked_table_maps() to THD::binlog_write_table_maps() as most other related binlog functions are in THD. - Removed binlog_write_table_map() and binlog_log_row_internal() as they are now obsolete as 'has_transactions()' is pre-calculated in prepare_for_row_logging(). - Remove 'is_transactional' argument from binlog_write_table_map() as this can now be read from handler. - Changed order of 'if's in handler::external_lock() and wsrep_mysqld.h to first evaluate fast and likely cases before more complex ones. - Added error checking in ha_write_row() and related functions if binlog_log_row() failed. - Don't clear check_table_binlog_row_based_result in clear_cached_table_binlog_row_based_flag() as it's not needed. - THD::clear_binlog_table_maps() has been replaced with THD::reset_binlog_for_next_statement() - Added 'MYSQL_OPEN_IGNORE_LOGGING_FORMAT' flag to open_and_lock_tables() to avoid calculating of binary log format for internal opens. This flag is also used to avoid reading statistics tables for internal tables. - Added OPTION_BINLOG_LOG_OFF as a simple way to turn of binlog temporary for create (instead of using THD::sql_log_bin_off. - Removed flag THD::sql_log_bin_off (not needed anymore) - Speed up THD::decide_logging_format() by remembering if blackhole engine is used and avoid a loop over all tables if it's not used (the common case). - THD::decide_logging_format() is not called anymore if no tables are used for the statement. This will speed up pure stored procedure code with about 5%+ according to some simple tests. - We now get annotated events on slave if a CREATE ... SELECT statement is transformed on the slave from statement to row logging. - In the original code, the master could come into a state where row logging is enforced for all future events if statement could be used. This is now partly fixed. Other changes: - Ensure that all tables used by a statement has query_id set. - Had to restore the row_logging flag for not used tables in THD::binlog_write_table_maps (not normal scenario) - Removed injector::transaction::use_table(server_id_type sid, table tbl) as it's not used. - Cleaned up set_slave_thread_options() - Some more DBUG_ENTER/DBUG_RETURN, code comments and minor indentation changes. - Ensure we only call THD::decide_logging_format_low() once in mysql_insert() (inefficiency). - Don't annotate INSERT DELAYED - Removed zeroing pos_in_table_list in THD::open_temporary_table() as it's already 0
This commit is contained in:
22
mysql-test/suite/binlog/t/foreign_key.test
Normal file
22
mysql-test/suite/binlog/t/foreign_key.test
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_binlog_format_row.inc
|
||||||
|
|
||||||
|
reset master;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id INT,
|
||||||
|
k INT,
|
||||||
|
c CHAR(8),
|
||||||
|
KEY (k),
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
FOREIGN KEY (id) REFERENCES t1 (k)
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
LOCK TABLES t1 WRITE;
|
||||||
|
SET SESSION FOREIGN_KEY_CHECKS= OFF;
|
||||||
|
SET AUTOCOMMIT=OFF;
|
||||||
|
INSERT INTO t1 VALUES (1,1,'foo');
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET SESSION FOREIGN_KEY_CHECKS= ON;
|
||||||
|
SET AUTOCOMMIT=ON;
|
||||||
|
|
||||||
|
source include/show_binlog_events.inc;
|
@@ -85,9 +85,12 @@ master-bin.000001 # Gtid # # GTID #-#-#
|
|||||||
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */
|
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */
|
||||||
master-bin.000001 # Gtid # # GTID #-#-#
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
master-bin.000001 # Query # # use `test`; create table t1 (a int)
|
master-bin.000001 # Query # # use `test`; create table t1 (a int)
|
||||||
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `test`.`t1`/* Generated to handle failed CREATE OR REPLACE */
|
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `test`.`t1`/* Generated to handle failed CREATE OR REPLACE */
|
||||||
master-bin.000001 # Query # # ROLLBACK
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; create temporary table t9 (a int)
|
||||||
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`t9`/* Generated to handle failed CREATE OR REPLACE */
|
||||||
connection server_2;
|
connection server_2;
|
||||||
show tables;
|
show tables;
|
||||||
Tables_in_test
|
Tables_in_test
|
||||||
@@ -154,7 +157,7 @@ slave-bin.000001 # Query # # use `test`; create table t4 (server_2_to_be_delete
|
|||||||
slave-bin.000001 # Gtid # # GTID #-#-#
|
slave-bin.000001 # Gtid # # GTID #-#-#
|
||||||
slave-bin.000001 # Query # # use `test`; create table t1 (new_table int)
|
slave-bin.000001 # Query # # use `test`; create table t1 (new_table int)
|
||||||
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t2` (
|
slave-bin.000001 # Query # # use `test`; CREATE OR REPLACE TABLE `t2` (
|
||||||
`a` int(11) DEFAULT NULL
|
`a` int(11) DEFAULT NULL
|
||||||
)
|
)
|
||||||
slave-bin.000001 # Annotate_rows # # create table t2 select * from t9
|
slave-bin.000001 # Annotate_rows # # create table t2 select * from t9
|
||||||
@@ -223,26 +226,12 @@ Log_name Pos Event_type Server_id End_log_pos Info
|
|||||||
slave-bin.000001 # Gtid # # GTID #-#-#
|
slave-bin.000001 # Gtid # # GTID #-#-#
|
||||||
slave-bin.000001 # Query # # use `test`; create table t1 (a int)
|
slave-bin.000001 # Query # # use `test`; create table t1 (a int)
|
||||||
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
slave-bin.000001 # Annotate_rows # # insert into t1 values (0),(1),(2)
|
slave-bin.000001 # Query # # use `test`; insert into t1 values (0),(1),(2)
|
||||||
slave-bin.000001 # Table_map # # table_id: # (test.t1)
|
|
||||||
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
||||||
slave-bin.000001 # Query # # COMMIT
|
slave-bin.000001 # Query # # COMMIT
|
||||||
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
slave-bin.000001 # Gtid # # GTID #-#-#
|
||||||
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t2` (
|
slave-bin.000001 # Query # # use `test`; create table t2 engine=myisam select * from t1
|
||||||
`a` int(11) DEFAULT NULL
|
slave-bin.000001 # Gtid # # GTID #-#-#
|
||||||
) ENGINE=MyISAM
|
slave-bin.000001 # Query # # use `test`; create or replace table t2 engine=innodb select * from t1
|
||||||
slave-bin.000001 # Annotate_rows # # create table t2 engine=myisam select * from t1
|
|
||||||
slave-bin.000001 # Table_map # # table_id: # (test.t2)
|
|
||||||
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
||||||
slave-bin.000001 # Query # # COMMIT
|
|
||||||
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|
||||||
slave-bin.000001 # Query # # use `test`; CREATE OR REPLACE TABLE `t2` (
|
|
||||||
`a` int(11) DEFAULT NULL
|
|
||||||
) ENGINE=InnoDB
|
|
||||||
slave-bin.000001 # Annotate_rows # # create or replace table t2 engine=innodb select * from t1
|
|
||||||
slave-bin.000001 # Table_map # # table_id: # (test.t2)
|
|
||||||
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
||||||
slave-bin.000001 # Xid # # COMMIT /* XID */
|
|
||||||
connection server_1;
|
connection server_1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
#
|
#
|
||||||
|
@@ -160,6 +160,7 @@ slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|||||||
slave-bin.000001 # Query # # use `test`; CREATE OR REPLACE TABLE `t2` (
|
slave-bin.000001 # Query # # use `test`; CREATE OR REPLACE TABLE `t2` (
|
||||||
`a` int(11) DEFAULT NULL
|
`a` int(11) DEFAULT NULL
|
||||||
)
|
)
|
||||||
|
slave-bin.000001 # Annotate_rows # # create table t2 select * from t9
|
||||||
slave-bin.000001 # Table_map # # table_id: # (test.t2)
|
slave-bin.000001 # Table_map # # table_id: # (test.t2)
|
||||||
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
||||||
slave-bin.000001 # Query # # COMMIT
|
slave-bin.000001 # Query # # COMMIT
|
||||||
@@ -171,6 +172,7 @@ slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|||||||
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t5` (
|
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t5` (
|
||||||
`a` int(11) DEFAULT NULL
|
`a` int(11) DEFAULT NULL
|
||||||
)
|
)
|
||||||
|
slave-bin.000001 # Annotate_rows # # create table t5 select * from t9
|
||||||
slave-bin.000001 # Table_map # # table_id: # (test.t5)
|
slave-bin.000001 # Table_map # # table_id: # (test.t5)
|
||||||
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
||||||
slave-bin.000001 # Query # # COMMIT
|
slave-bin.000001 # Query # # COMMIT
|
||||||
|
@@ -56,6 +56,7 @@ create or replace table t1 (a int primary key) select a from t2;
|
|||||||
|
|
||||||
# Same with temporary table
|
# Same with temporary table
|
||||||
create temporary table t9 (a int);
|
create temporary table t9 (a int);
|
||||||
|
|
||||||
--error ER_DUP_ENTRY
|
--error ER_DUP_ENTRY
|
||||||
create or replace temporary table t9 (a int primary key) select a from t2;
|
create or replace temporary table t9 (a int primary key) select a from t2;
|
||||||
|
|
||||||
|
@@ -1241,15 +1241,9 @@ Events::load_events_from_db(THD *thd)
|
|||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
/* All the dmls to mysql.events tables are stmt bin-logged. */
|
/* All the dmls to mysql.events tables are stmt bin-logged. */
|
||||||
bool save_binlog_row_based;
|
table->file->row_logging= 0;
|
||||||
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
|
|
||||||
thd->set_current_stmt_binlog_format_stmt();
|
|
||||||
|
|
||||||
(void) table->file->ha_update_row(table->record[1], table->record[0]);
|
(void) table->file->ha_update_row(table->record[1], table->record[0]);
|
||||||
|
|
||||||
if (save_binlog_row_based)
|
|
||||||
thd->set_current_stmt_binlog_format_row();
|
|
||||||
|
|
||||||
delete et;
|
delete et;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -2131,12 +2131,10 @@ int ha_partition::copy_partitions(ulonglong * const copied,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
THD *thd= ha_thd();
|
|
||||||
/* Copy record to new handler */
|
/* Copy record to new handler */
|
||||||
(*copied)++;
|
(*copied)++;
|
||||||
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
|
DBUG_ASSERT(!m_new_file[new_part]->row_logging);
|
||||||
result= m_new_file[new_part]->ha_write_row(m_rec0);
|
result= m_new_file[new_part]->ha_write_row(m_rec0);
|
||||||
reenable_binlog(thd);
|
|
||||||
if (result)
|
if (result)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -4374,11 +4372,10 @@ int ha_partition::write_row(const uchar * buf)
|
|||||||
|
|
||||||
start_part_bulk_insert(thd, part_id);
|
start_part_bulk_insert(thd, part_id);
|
||||||
|
|
||||||
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
|
DBUG_ASSERT(!m_file[part_id]->row_logging);
|
||||||
error= m_file[part_id]->ha_write_row(buf);
|
error= m_file[part_id]->ha_write_row(buf);
|
||||||
if (have_auto_increment && !table->s->next_number_keypart)
|
if (have_auto_increment && !table->s->next_number_keypart)
|
||||||
set_auto_increment_if_higher(table->next_number_field);
|
set_auto_increment_if_higher(table->next_number_field);
|
||||||
reenable_binlog(thd);
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
table->auto_increment_field_not_null= saved_auto_inc_field_not_null;
|
table->auto_increment_field_not_null= saved_auto_inc_field_not_null;
|
||||||
@@ -4457,12 +4454,11 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data)
|
|||||||
|
|
||||||
m_last_part= new_part_id;
|
m_last_part= new_part_id;
|
||||||
start_part_bulk_insert(thd, new_part_id);
|
start_part_bulk_insert(thd, new_part_id);
|
||||||
|
DBUG_ASSERT(!m_file[new_part_id]->row_logging);
|
||||||
if (new_part_id == old_part_id)
|
if (new_part_id == old_part_id)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Update in partition %u", (uint) new_part_id));
|
DBUG_PRINT("info", ("Update in partition %u", (uint) new_part_id));
|
||||||
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
|
|
||||||
error= m_file[new_part_id]->ha_update_row(old_data, new_data);
|
error= m_file[new_part_id]->ha_update_row(old_data, new_data);
|
||||||
reenable_binlog(thd);
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -4481,16 +4477,12 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data)
|
|||||||
table->next_number_field= NULL;
|
table->next_number_field= NULL;
|
||||||
DBUG_PRINT("info", ("Update from partition %u to partition %u",
|
DBUG_PRINT("info", ("Update from partition %u to partition %u",
|
||||||
(uint) old_part_id, (uint) new_part_id));
|
(uint) old_part_id, (uint) new_part_id));
|
||||||
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
|
|
||||||
error= m_file[new_part_id]->ha_write_row((uchar*) new_data);
|
error= m_file[new_part_id]->ha_write_row((uchar*) new_data);
|
||||||
reenable_binlog(thd);
|
|
||||||
table->next_number_field= saved_next_number_field;
|
table->next_number_field= saved_next_number_field;
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
|
|
||||||
error= m_file[old_part_id]->ha_delete_row(old_data);
|
error= m_file[old_part_id]->ha_delete_row(old_data);
|
||||||
reenable_binlog(thd);
|
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -4592,9 +4584,8 @@ int ha_partition::delete_row(const uchar *buf)
|
|||||||
if (!bitmap_is_set(&(m_part_info->lock_partitions), m_last_part))
|
if (!bitmap_is_set(&(m_part_info->lock_partitions), m_last_part))
|
||||||
DBUG_RETURN(HA_ERR_NOT_IN_LOCK_PARTITIONS);
|
DBUG_RETURN(HA_ERR_NOT_IN_LOCK_PARTITIONS);
|
||||||
|
|
||||||
tmp_disable_binlog(thd);
|
DBUG_ASSERT(!m_file[m_last_part]->row_logging);
|
||||||
error= m_file[m_last_part]->ha_delete_row(buf);
|
error= m_file[m_last_part]->ha_delete_row(buf);
|
||||||
reenable_binlog(thd);
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -202,7 +202,11 @@ int ha_sequence::write_row(const uchar *buf)
|
|||||||
DBUG_ENTER("ha_sequence::write_row");
|
DBUG_ENTER("ha_sequence::write_row");
|
||||||
DBUG_ASSERT(table->record[0] == buf);
|
DBUG_ASSERT(table->record[0] == buf);
|
||||||
|
|
||||||
row_already_logged= 0;
|
/*
|
||||||
|
Log to binary log even if this function has been called before
|
||||||
|
(The function ends by setting row_logging to 0)
|
||||||
|
*/
|
||||||
|
row_logging= row_logging_init;
|
||||||
if (unlikely(sequence->initialized == SEQUENCE::SEQ_IN_PREPARE))
|
if (unlikely(sequence->initialized == SEQUENCE::SEQ_IN_PREPARE))
|
||||||
{
|
{
|
||||||
/* This calls is from ha_open() as part of create table */
|
/* This calls is from ha_open() as part of create table */
|
||||||
@@ -218,6 +222,7 @@ int ha_sequence::write_row(const uchar *buf)
|
|||||||
sequence->copy(&tmp_seq);
|
sequence->copy(&tmp_seq);
|
||||||
if (likely(!(error= file->write_row(buf))))
|
if (likely(!(error= file->write_row(buf))))
|
||||||
sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
|
sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
|
||||||
|
row_logging= 0;
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
if (unlikely(sequence->initialized != SEQUENCE::SEQ_READY_TO_USE))
|
if (unlikely(sequence->initialized != SEQUENCE::SEQ_READY_TO_USE))
|
||||||
@@ -262,10 +267,12 @@ int ha_sequence::write_row(const uchar *buf)
|
|||||||
sequence->copy(&tmp_seq);
|
sequence->copy(&tmp_seq);
|
||||||
rows_changed++;
|
rows_changed++;
|
||||||
/* We have to do the logging while we hold the sequence mutex */
|
/* We have to do the logging while we hold the sequence mutex */
|
||||||
error= binlog_log_row(table, 0, buf, log_func);
|
if (row_logging)
|
||||||
row_already_logged= 1;
|
error= binlog_log_row(table, 0, buf, log_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Row is already logged, don't log it again in ha_write_row() */
|
||||||
|
row_logging= 0;
|
||||||
sequence->all_values_used= 0;
|
sequence->all_values_used= 0;
|
||||||
if (!sequence_locked)
|
if (!sequence_locked)
|
||||||
sequence->write_unlock(table);
|
sequence->write_unlock(table);
|
||||||
|
315
sql/handler.cc
315
sql/handler.cc
@@ -3620,8 +3620,9 @@ int handler::update_auto_increment()
|
|||||||
variables->auto_increment_increment);
|
variables->auto_increment_increment);
|
||||||
auto_inc_intervals_count++;
|
auto_inc_intervals_count++;
|
||||||
/* Row-based replication does not need to store intervals in binlog */
|
/* Row-based replication does not need to store intervals in binlog */
|
||||||
if (((WSREP(thd) && wsrep_emulate_bin_log ) || mysql_bin_log.is_open())
|
if (((WSREP_NNULL(thd) && wsrep_emulate_bin_log) ||
|
||||||
&& !thd->is_current_stmt_binlog_format_row())
|
mysql_bin_log.is_open()) &&
|
||||||
|
!thd->is_current_stmt_binlog_format_row())
|
||||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.
|
thd->auto_inc_intervals_in_cur_stmt_for_binlog.
|
||||||
append(auto_inc_interval_for_cur_row.minimum(),
|
append(auto_inc_interval_for_cur_row.minimum(),
|
||||||
auto_inc_interval_for_cur_row.values(),
|
auto_inc_interval_for_cur_row.values(),
|
||||||
@@ -6366,32 +6367,35 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
|
|||||||
1 Row needs to be logged
|
1 Row needs to be logged
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool handler::check_table_binlog_row_based(bool binlog_row)
|
bool handler::check_table_binlog_row_based()
|
||||||
{
|
{
|
||||||
if (table->versioned(VERS_TRX_ID))
|
|
||||||
return false;
|
|
||||||
if (unlikely((table->in_use->variables.sql_log_bin_off)))
|
|
||||||
return 0; /* Called by partitioning engine */
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
if (!table->in_use->variables.sql_log_bin &&
|
|
||||||
wsrep_thd_is_applying(table->in_use))
|
|
||||||
return 0; /* wsrep patch sets sql_log_bin to silence binlogging
|
|
||||||
from high priority threads */
|
|
||||||
#endif /* WITH_WSREP */
|
|
||||||
if (unlikely((!check_table_binlog_row_based_done)))
|
if (unlikely((!check_table_binlog_row_based_done)))
|
||||||
{
|
{
|
||||||
check_table_binlog_row_based_done= 1;
|
check_table_binlog_row_based_done= 1;
|
||||||
check_table_binlog_row_based_result=
|
check_table_binlog_row_based_result=
|
||||||
check_table_binlog_row_based_internal(binlog_row);
|
check_table_binlog_row_based_internal();
|
||||||
}
|
}
|
||||||
return check_table_binlog_row_based_result;
|
return check_table_binlog_row_based_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handler::check_table_binlog_row_based_internal(bool binlog_row)
|
bool handler::check_table_binlog_row_based_internal()
|
||||||
{
|
{
|
||||||
THD *thd= table->in_use;
|
THD *thd= table->in_use;
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
if (!thd->variables.sql_log_bin &&
|
||||||
|
wsrep_thd_is_applying(table->in_use))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
wsrep patch sets sql_log_bin to silence binlogging from high
|
||||||
|
priority threads
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return (table->s->can_do_row_logging &&
|
return (table->s->can_do_row_logging &&
|
||||||
|
!table->versioned(VERS_TRX_ID) &&
|
||||||
|
!(thd->variables.option_bits & OPTION_BIN_TMP_LOG_OFF) &&
|
||||||
thd->is_current_stmt_binlog_format_row() &&
|
thd->is_current_stmt_binlog_format_row() &&
|
||||||
/*
|
/*
|
||||||
Wsrep partially enables binary logging if it have not been
|
Wsrep partially enables binary logging if it have not been
|
||||||
@@ -6407,9 +6411,9 @@ bool handler::check_table_binlog_row_based_internal(bool binlog_row)
|
|||||||
|
|
||||||
Otherwise, return 'true' if binary logging is on.
|
Otherwise, return 'true' if binary logging is on.
|
||||||
*/
|
*/
|
||||||
IF_WSREP(((WSREP_EMULATE_BINLOG(thd) &&
|
IF_WSREP(((WSREP_EMULATE_BINLOG_NNULL(thd) &&
|
||||||
wsrep_thd_is_local(thd)) ||
|
wsrep_thd_is_local(thd)) ||
|
||||||
((WSREP(thd) ||
|
((WSREP_NNULL(thd) ||
|
||||||
(thd->variables.option_bits & OPTION_BIN_LOG)) &&
|
(thd->variables.option_bits & OPTION_BIN_LOG)) &&
|
||||||
mysql_bin_log.is_open())),
|
mysql_bin_log.is_open())),
|
||||||
(thd->variables.option_bits & OPTION_BIN_LOG) &&
|
(thd->variables.option_bits & OPTION_BIN_LOG) &&
|
||||||
@@ -6417,151 +6421,22 @@ bool handler::check_table_binlog_row_based_internal(bool binlog_row)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @brief
|
int handler::binlog_log_row(TABLE *table,
|
||||||
Write table maps for all (manually or automatically) locked tables
|
const uchar *before_record,
|
||||||
to the binary log. Also, if binlog_annotate_row_events is ON,
|
const uchar *after_record,
|
||||||
write Annotate_rows event before the first table map.
|
Log_func *log_func)
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
write_locked_table_maps()
|
|
||||||
thd Pointer to THD structure
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
This function will generate and write table maps for all tables
|
|
||||||
that are locked by the thread 'thd'.
|
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
0 All OK
|
|
||||||
1 Failed to write all table maps
|
|
||||||
|
|
||||||
SEE ALSO
|
|
||||||
THD::lock
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int write_locked_table_maps(THD *thd)
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("write_locked_table_maps");
|
bool error;
|
||||||
DBUG_PRINT("enter", ("thd:%p thd->lock:%p "
|
THD *thd= table->in_use;
|
||||||
"thd->extra_lock: %p",
|
DBUG_ENTER("binlog_log_row");
|
||||||
thd, thd->lock, thd->extra_lock));
|
|
||||||
|
|
||||||
DBUG_PRINT("debug", ("get_binlog_table_maps(): %d", thd->get_binlog_table_maps()));
|
if (!thd->binlog_table_maps &&
|
||||||
|
thd->binlog_write_table_maps())
|
||||||
|
DBUG_RETURN(HA_ERR_RBR_LOGGING_FAILED);
|
||||||
|
|
||||||
MYSQL_LOCK *locks[2];
|
error= (*log_func)(thd, table, row_logging_has_trans,
|
||||||
locks[0]= thd->extra_lock;
|
before_record, after_record);
|
||||||
locks[1]= thd->lock;
|
DBUG_RETURN(error ? HA_ERR_RBR_LOGGING_FAILED : 0);
|
||||||
my_bool with_annotate= IF_WSREP(!wsrep_fragments_certified_for_stmt(thd),
|
|
||||||
true) &&
|
|
||||||
thd->variables.binlog_annotate_row_events &&
|
|
||||||
thd->query() && thd->query_length();
|
|
||||||
|
|
||||||
for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
|
|
||||||
{
|
|
||||||
MYSQL_LOCK const *const lock= locks[i];
|
|
||||||
if (lock == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
TABLE **const end_ptr= lock->table + lock->table_count;
|
|
||||||
for (TABLE **table_ptr= lock->table ;
|
|
||||||
table_ptr != end_ptr ;
|
|
||||||
++table_ptr)
|
|
||||||
{
|
|
||||||
TABLE *const table= *table_ptr;
|
|
||||||
if (table->current_lock == F_WRLCK &&
|
|
||||||
table->file->check_table_binlog_row_based(0))
|
|
||||||
{
|
|
||||||
if (binlog_write_table_map(thd, table, with_annotate))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
with_annotate= 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int binlog_write_table_map(THD *thd, TABLE *table, bool with_annotate)
|
|
||||||
{
|
|
||||||
DBUG_ENTER("binlog_write_table_map");
|
|
||||||
DBUG_PRINT("info", ("table %s", table->s->table_name.str));
|
|
||||||
/*
|
|
||||||
We need to have a transactional behavior for SQLCOM_CREATE_TABLE
|
|
||||||
(e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
|
|
||||||
compatible behavior with the STMT based replication even when
|
|
||||||
the table is not transactional. In other words, if the operation
|
|
||||||
fails while executing the insert phase nothing is written to the
|
|
||||||
binlog.
|
|
||||||
|
|
||||||
Note that at this point, we check the type of a set of tables to
|
|
||||||
create the table map events. In the function binlog_log_row(),
|
|
||||||
which calls the current function, we check the type of the table
|
|
||||||
of the current row.
|
|
||||||
*/
|
|
||||||
bool const has_trans= ((sql_command_flags[thd->lex->sql_command] &
|
|
||||||
(CF_SCHEMA_CHANGE | CF_ADMIN_COMMAND)) ||
|
|
||||||
table->file->has_transactions());
|
|
||||||
int const error= thd->binlog_write_table_map(table, has_trans,
|
|
||||||
&with_annotate);
|
|
||||||
/*
|
|
||||||
If an error occurs, it is the responsibility of the caller to
|
|
||||||
roll back the transaction.
|
|
||||||
*/
|
|
||||||
if (unlikely(error))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int binlog_log_row_internal(TABLE* table,
|
|
||||||
const uchar *before_record,
|
|
||||||
const uchar *after_record,
|
|
||||||
Log_func *log_func)
|
|
||||||
{
|
|
||||||
bool error= 0;
|
|
||||||
THD *const thd= table->in_use;
|
|
||||||
|
|
||||||
/*
|
|
||||||
If there are no table maps written to the binary log, this is
|
|
||||||
the first row handled in this statement. In that case, we need
|
|
||||||
to write table maps for all locked tables to the binary log.
|
|
||||||
*/
|
|
||||||
if (likely(!(error= ((thd->get_binlog_table_maps() == 0 &&
|
|
||||||
write_locked_table_maps(thd))))))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
We need to have a transactional behavior for SQLCOM_CREATE_TABLE
|
|
||||||
(i.e. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
|
|
||||||
compatible behavior with the STMT based replication even when
|
|
||||||
the table is not transactional. In other words, if the operation
|
|
||||||
fails while executing the insert phase nothing is written to the
|
|
||||||
binlog. We need the same also for ALTER TABLE in the case we convert
|
|
||||||
a shared table to a not shared table as in this case we will log all
|
|
||||||
rows.
|
|
||||||
*/
|
|
||||||
bool const has_trans= ((sql_command_flags[thd->lex->sql_command] &
|
|
||||||
(CF_SCHEMA_CHANGE | CF_ADMIN_COMMAND)) ||
|
|
||||||
table->file->has_transactions());
|
|
||||||
error= (*log_func)(thd, table, has_trans, before_record, after_record);
|
|
||||||
}
|
|
||||||
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int binlog_log_row(TABLE* table, const uchar *before_record,
|
|
||||||
const uchar *after_record, Log_func *log_func)
|
|
||||||
{
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
THD *const thd= table->in_use;
|
|
||||||
|
|
||||||
/* only InnoDB tables will be replicated through binlog emulation */
|
|
||||||
if ((WSREP_EMULATE_BINLOG(thd) &&
|
|
||||||
!(table->file->partition_ht()->flags & HTON_WSREP_REPLICATION)) ||
|
|
||||||
thd->wsrep_ignore_table == true)
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!table->file->check_table_binlog_row_based(1))
|
|
||||||
return 0;
|
|
||||||
return binlog_log_row_internal(table, before_record, after_record, log_func);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -6647,6 +6522,7 @@ int handler::ha_external_lock(THD *thd, int lock_type)
|
|||||||
int handler::ha_reset()
|
int handler::ha_reset()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("ha_reset");
|
DBUG_ENTER("ha_reset");
|
||||||
|
|
||||||
/* Check that we have called all proper deallocation functions */
|
/* Check that we have called all proper deallocation functions */
|
||||||
DBUG_ASSERT((uchar*) table->def_read_set.bitmap +
|
DBUG_ASSERT((uchar*) table->def_read_set.bitmap +
|
||||||
table->s->column_bitmap_size ==
|
table->s->column_bitmap_size ==
|
||||||
@@ -6662,6 +6538,10 @@ int handler::ha_reset()
|
|||||||
pushed_cond= NULL;
|
pushed_cond= NULL;
|
||||||
tracker= NULL;
|
tracker= NULL;
|
||||||
mark_trx_read_write_done= 0;
|
mark_trx_read_write_done= 0;
|
||||||
|
/*
|
||||||
|
Disable row logging.
|
||||||
|
*/
|
||||||
|
row_logging= row_logging_init= 0;
|
||||||
clear_cached_table_binlog_row_based_flag();
|
clear_cached_table_binlog_row_based_flag();
|
||||||
/* Reset information about pushed engine conditions */
|
/* Reset information about pushed engine conditions */
|
||||||
cancel_pushed_idx_cond();
|
cancel_pushed_idx_cond();
|
||||||
@@ -6678,8 +6558,8 @@ static int wsrep_after_row(THD *thd)
|
|||||||
/* enforce wsrep_max_ws_rows */
|
/* enforce wsrep_max_ws_rows */
|
||||||
thd->wsrep_affected_rows++;
|
thd->wsrep_affected_rows++;
|
||||||
if (wsrep_max_ws_rows &&
|
if (wsrep_max_ws_rows &&
|
||||||
wsrep_thd_is_local(thd) &&
|
thd->wsrep_affected_rows > wsrep_max_ws_rows &&
|
||||||
thd->wsrep_affected_rows > wsrep_max_ws_rows)
|
wsrep_thd_is_local(thd))
|
||||||
{
|
{
|
||||||
trans_rollback_stmt(thd) || trans_rollback(thd);
|
trans_rollback_stmt(thd) || trans_rollback(thd);
|
||||||
my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
|
my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
|
||||||
@@ -6864,6 +6744,74 @@ static int check_duplicate_long_entries_update(TABLE *table, uchar *new_rec)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Check if galera disables binary logging for this table
|
||||||
|
|
||||||
|
@return 0 Binary logging disabled
|
||||||
|
@return 1 Binary logging can be enabled
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool wsrep_check_if_binlog_row(TABLE *table)
|
||||||
|
{
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
THD *const thd= table->in_use;
|
||||||
|
|
||||||
|
/* only InnoDB tables will be replicated through binlog emulation */
|
||||||
|
if ((WSREP_EMULATE_BINLOG(thd) &&
|
||||||
|
!(table->file->partition_ht()->flags & HTON_WSREP_REPLICATION)) ||
|
||||||
|
thd->wsrep_ignore_table == true)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepare handler for row logging
|
||||||
|
|
||||||
|
@return 0 if handler will not participate in row logging
|
||||||
|
@return 1 handler will participate in row logging
|
||||||
|
|
||||||
|
This function is always safe to call on an opened table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool handler::prepare_for_row_logging()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("handler::prepare_for_row_logging");
|
||||||
|
|
||||||
|
/* Check if we should have row logging */
|
||||||
|
if (wsrep_check_if_binlog_row(table) &&
|
||||||
|
check_table_binlog_row_based())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Row logging enabled. Intialize all variables and write
|
||||||
|
annotated and table maps
|
||||||
|
*/
|
||||||
|
row_logging= row_logging_init= 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We need to have a transactional behavior for SQLCOM_CREATE_TABLE
|
||||||
|
(e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
|
||||||
|
compatible behavior with the STMT based replication even when
|
||||||
|
the table is not transactional. In other words, if the operation
|
||||||
|
fails while executing the insert phase nothing is written to the
|
||||||
|
binlog.
|
||||||
|
*/
|
||||||
|
row_logging_has_trans=
|
||||||
|
((sql_command_flags[table->in_use->lex->sql_command] &
|
||||||
|
(CF_SCHEMA_CHANGE | CF_ADMIN_COMMAND)) ||
|
||||||
|
table->file->has_transactions());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check row_logging has not been properly cleared from previous command */
|
||||||
|
DBUG_ASSERT(row_logging == 0);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(row_logging);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
Do all initialization needed for insert
|
Do all initialization needed for insert
|
||||||
|
|
||||||
@param force_update_handler Set to TRUE if we should always create an
|
@param force_update_handler Set to TRUE if we should always create an
|
||||||
@@ -6891,7 +6839,6 @@ int handler::prepare_for_insert(bool force_update_handler)
|
|||||||
int handler::ha_write_row(const uchar *buf)
|
int handler::ha_write_row(const uchar *buf)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
|
|
||||||
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
|
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
|
||||||
m_lock_type == F_WRLCK);
|
m_lock_type == F_WRLCK);
|
||||||
DBUG_ENTER("handler::ha_write_row");
|
DBUG_ENTER("handler::ha_write_row");
|
||||||
@@ -6911,13 +6858,17 @@ int handler::ha_write_row(const uchar *buf)
|
|||||||
{ error= write_row(buf); })
|
{ error= write_row(buf); })
|
||||||
|
|
||||||
MYSQL_INSERT_ROW_DONE(error);
|
MYSQL_INSERT_ROW_DONE(error);
|
||||||
if (likely(!error) && !row_already_logged)
|
if (likely(!error))
|
||||||
{
|
{
|
||||||
rows_changed++;
|
rows_changed++;
|
||||||
error= binlog_log_row(table, 0, buf, log_func);
|
if (row_logging)
|
||||||
|
{
|
||||||
|
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
|
||||||
|
error= binlog_log_row(table, 0, buf, log_func);
|
||||||
|
}
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (table_share->tmp_table == NO_TMP_TABLE &&
|
if (WSREP_NNULL(ha_thd()) && table_share->tmp_table == NO_TMP_TABLE &&
|
||||||
WSREP(ha_thd()) && (error= wsrep_after_row(ha_thd())))
|
!error && (error= wsrep_after_row(ha_thd())))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
@@ -6932,10 +6883,8 @@ int handler::ha_write_row(const uchar *buf)
|
|||||||
int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
|
int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
|
|
||||||
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
|
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
|
||||||
m_lock_type == F_WRLCK);
|
m_lock_type == F_WRLCK);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some storage engines require that the new record is in record[0]
|
Some storage engines require that the new record is in record[0]
|
||||||
(and the old record is in record[1]).
|
(and the old record is in record[1]).
|
||||||
@@ -6950,20 +6899,22 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
|
|||||||
(error= check_duplicate_long_entries_update(table, (uchar*) new_data)))
|
(error= check_duplicate_long_entries_update(table, (uchar*) new_data)))
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
TABLE_IO_WAIT(tracker, PSI_TABLE_UPDATE_ROW, active_index, error,
|
TABLE_IO_WAIT(tracker, PSI_TABLE_UPDATE_ROW, active_index, 0,
|
||||||
{ error= update_row(old_data, new_data);})
|
{ error= update_row(old_data, new_data);})
|
||||||
|
|
||||||
MYSQL_UPDATE_ROW_DONE(error);
|
MYSQL_UPDATE_ROW_DONE(error);
|
||||||
if (likely(!error) && !row_already_logged)
|
if (likely(!error))
|
||||||
{
|
{
|
||||||
rows_changed++;
|
rows_changed++;
|
||||||
error= binlog_log_row(table, old_data, new_data, log_func);
|
if (row_logging)
|
||||||
#ifdef WITH_WSREP
|
|
||||||
if (table_share->tmp_table == NO_TMP_TABLE &&
|
|
||||||
WSREP(ha_thd()) && (error= wsrep_after_row(ha_thd())))
|
|
||||||
{
|
{
|
||||||
return error;
|
Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
|
||||||
|
error= binlog_log_row(table, old_data, new_data, log_func);
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
if (WSREP_NNULL(ha_thd()) && table_share->tmp_table == NO_TMP_TABLE &&
|
||||||
|
!error && (error= wsrep_after_row(ha_thd())))
|
||||||
|
return error;
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
@@ -7000,7 +6951,6 @@ int handler::update_first_row(const uchar *new_data)
|
|||||||
int handler::ha_delete_row(const uchar *buf)
|
int handler::ha_delete_row(const uchar *buf)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
|
|
||||||
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
|
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
|
||||||
m_lock_type == F_WRLCK);
|
m_lock_type == F_WRLCK);
|
||||||
/*
|
/*
|
||||||
@@ -7019,10 +6969,14 @@ int handler::ha_delete_row(const uchar *buf)
|
|||||||
if (likely(!error))
|
if (likely(!error))
|
||||||
{
|
{
|
||||||
rows_changed++;
|
rows_changed++;
|
||||||
error= binlog_log_row(table, buf, 0, log_func);
|
if (row_logging)
|
||||||
|
{
|
||||||
|
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
|
||||||
|
error= binlog_log_row(table, buf, 0, log_func);
|
||||||
|
}
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (table_share->tmp_table == NO_TMP_TABLE &&
|
if (WSREP_NNULL(ha_thd()) && table_share->tmp_table == NO_TMP_TABLE &&
|
||||||
WSREP(ha_thd()) && (error= wsrep_after_row(ha_thd())))
|
!error && (error= wsrep_after_row(ha_thd())))
|
||||||
{
|
{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -7049,11 +7003,10 @@ int handler::ha_delete_row(const uchar *buf)
|
|||||||
int handler::ha_direct_update_rows(ha_rows *update_rows, ha_rows *found_rows)
|
int handler::ha_direct_update_rows(ha_rows *update_rows, ha_rows *found_rows)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
|
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||||
mark_trx_read_write();
|
mark_trx_read_write();
|
||||||
|
|
||||||
error = direct_update_rows(update_rows, found_rows);
|
error= direct_update_rows(update_rows, found_rows);
|
||||||
MYSQL_UPDATE_ROW_DONE(error);
|
MYSQL_UPDATE_ROW_DONE(error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@@ -610,6 +610,7 @@ given at all. */
|
|||||||
#define HA_CREATE_USED_SEQUENCE (1UL << 25)
|
#define HA_CREATE_USED_SEQUENCE (1UL << 25)
|
||||||
|
|
||||||
typedef ulonglong alter_table_operations;
|
typedef ulonglong alter_table_operations;
|
||||||
|
typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These flags are set by the parser and describes the type of
|
These flags are set by the parser and describes the type of
|
||||||
@@ -3050,8 +3051,6 @@ public:
|
|||||||
bool mark_trx_read_write_done; /* mark_trx_read_write was called */
|
bool mark_trx_read_write_done; /* mark_trx_read_write was called */
|
||||||
bool check_table_binlog_row_based_done; /* check_table_binlog.. was called */
|
bool check_table_binlog_row_based_done; /* check_table_binlog.. was called */
|
||||||
bool check_table_binlog_row_based_result; /* cached check_table_binlog... */
|
bool check_table_binlog_row_based_result; /* cached check_table_binlog... */
|
||||||
/* Set to 1 if handler logged last insert/update/delete operation */
|
|
||||||
bool row_already_logged;
|
|
||||||
/*
|
/*
|
||||||
TRUE <=> the engine guarantees that returned records are within the range
|
TRUE <=> the engine guarantees that returned records are within the range
|
||||||
being scanned.
|
being scanned.
|
||||||
@@ -3192,10 +3191,16 @@ public:
|
|||||||
void end_psi_batch_mode();
|
void end_psi_batch_mode();
|
||||||
|
|
||||||
bool set_top_table_fields;
|
bool set_top_table_fields;
|
||||||
|
|
||||||
struct TABLE *top_table;
|
struct TABLE *top_table;
|
||||||
Field **top_table_field;
|
Field **top_table_field;
|
||||||
uint top_table_fields;
|
uint top_table_fields;
|
||||||
|
|
||||||
|
/* If we have row logging enabled for this table */
|
||||||
|
bool row_logging, row_logging_init;
|
||||||
|
/* If the row logging should be done in transaction cache */
|
||||||
|
bool row_logging_has_trans;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
The lock type set by when calling::ha_external_lock(). This is
|
The lock type set by when calling::ha_external_lock(). This is
|
||||||
@@ -3213,7 +3218,6 @@ private:
|
|||||||
/** Stores next_insert_id for handling duplicate key errors. */
|
/** Stores next_insert_id for handling duplicate key errors. */
|
||||||
ulonglong m_prev_insert_id;
|
ulonglong m_prev_insert_id;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
|
handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
|
||||||
:table_share(share_arg), table(0),
|
:table_share(share_arg), table(0),
|
||||||
@@ -3223,7 +3227,6 @@ public:
|
|||||||
mark_trx_read_write_done(0),
|
mark_trx_read_write_done(0),
|
||||||
check_table_binlog_row_based_done(0),
|
check_table_binlog_row_based_done(0),
|
||||||
check_table_binlog_row_based_result(0),
|
check_table_binlog_row_based_result(0),
|
||||||
row_already_logged(0),
|
|
||||||
in_range_check_pushed_down(FALSE), errkey(-1),
|
in_range_check_pushed_down(FALSE), errkey(-1),
|
||||||
key_used_on_scan(MAX_KEY),
|
key_used_on_scan(MAX_KEY),
|
||||||
active_index(MAX_KEY), keyread(MAX_KEY),
|
active_index(MAX_KEY), keyread(MAX_KEY),
|
||||||
@@ -3242,6 +3245,7 @@ public:
|
|||||||
m_psi_locker(NULL),
|
m_psi_locker(NULL),
|
||||||
set_top_table_fields(FALSE), top_table(0),
|
set_top_table_fields(FALSE), top_table(0),
|
||||||
top_table_field(0), top_table_fields(0),
|
top_table_field(0), top_table_fields(0),
|
||||||
|
row_logging(0), row_logging_init(0),
|
||||||
m_lock_type(F_UNLCK), ha_share(NULL), m_prev_insert_id(0)
|
m_lock_type(F_UNLCK), ha_share(NULL), m_prev_insert_id(0)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",
|
DBUG_PRINT("info",
|
||||||
@@ -4598,13 +4602,17 @@ protected:
|
|||||||
virtual int delete_table(const char *name);
|
virtual int delete_table(const char *name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool check_table_binlog_row_based(bool binlog_row);
|
bool check_table_binlog_row_based();
|
||||||
|
bool prepare_for_row_logging();
|
||||||
int prepare_for_insert(bool force_update_handler= 0);
|
int prepare_for_insert(bool force_update_handler= 0);
|
||||||
|
int binlog_log_row(TABLE *table,
|
||||||
|
const uchar *before_record,
|
||||||
|
const uchar *after_record,
|
||||||
|
Log_func *log_func);
|
||||||
|
|
||||||
inline void clear_cached_table_binlog_row_based_flag()
|
inline void clear_cached_table_binlog_row_based_flag()
|
||||||
{
|
{
|
||||||
check_table_binlog_row_based_done= 0;
|
check_table_binlog_row_based_done= 0;
|
||||||
check_table_binlog_row_based_result= 0;
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
/* Cache result to avoid extra calls */
|
/* Cache result to avoid extra calls */
|
||||||
@@ -4619,7 +4627,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void mark_trx_read_write_internal();
|
void mark_trx_read_write_internal();
|
||||||
bool check_table_binlog_row_based_internal(bool binlog_row);
|
bool check_table_binlog_row_based_internal();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*
|
/*
|
||||||
@@ -5202,7 +5210,6 @@ int binlog_log_row(TABLE* table,
|
|||||||
if (unlikely(this_tracker)) \
|
if (unlikely(this_tracker)) \
|
||||||
tracker->stop_tracking(table->in_use); \
|
tracker->stop_tracking(table->in_use); \
|
||||||
}
|
}
|
||||||
int binlog_write_table_map(THD *thd, TABLE *table, bool with_annotate);
|
|
||||||
void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag);
|
void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag);
|
||||||
void print_keydup_error(TABLE *table, KEY *key, myf errflag);
|
void print_keydup_error(TABLE *table, KEY *key, myf errflag);
|
||||||
|
|
||||||
|
179
sql/log.cc
179
sql/log.cc
@@ -514,6 +514,12 @@ void Log_event_writer::add_status(enum_logged_status status)
|
|||||||
cache_data->add_status(status);
|
cache_data->add_status(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Log_event_writer::set_incident()
|
||||||
|
{
|
||||||
|
cache_data->set_incident();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class binlog_cache_mngr {
|
class binlog_cache_mngr {
|
||||||
public:
|
public:
|
||||||
binlog_cache_mngr(my_off_t param_max_binlog_stmt_cache_size,
|
binlog_cache_mngr(my_off_t param_max_binlog_stmt_cache_size,
|
||||||
@@ -714,7 +720,6 @@ bool Log_to_csv_event_handler::
|
|||||||
uint field_index;
|
uint field_index;
|
||||||
Silence_log_table_errors error_handler;
|
Silence_log_table_errors error_handler;
|
||||||
Open_tables_backup open_tables_backup;
|
Open_tables_backup open_tables_backup;
|
||||||
ulonglong save_thd_options;
|
|
||||||
bool save_time_zone_used;
|
bool save_time_zone_used;
|
||||||
DBUG_ENTER("log_general");
|
DBUG_ENTER("log_general");
|
||||||
|
|
||||||
@@ -724,9 +729,6 @@ bool Log_to_csv_event_handler::
|
|||||||
*/
|
*/
|
||||||
save_time_zone_used= thd->time_zone_used;
|
save_time_zone_used= thd->time_zone_used;
|
||||||
|
|
||||||
save_thd_options= thd->variables.option_bits;
|
|
||||||
thd->variables.option_bits&= ~OPTION_BIN_LOG;
|
|
||||||
|
|
||||||
table_list.init_one_table(&MYSQL_SCHEMA_NAME, &GENERAL_LOG_NAME, 0,
|
table_list.init_one_table(&MYSQL_SCHEMA_NAME, &GENERAL_LOG_NAME, 0,
|
||||||
TL_WRITE_CONCURRENT_INSERT);
|
TL_WRITE_CONCURRENT_INSERT);
|
||||||
|
|
||||||
@@ -806,7 +808,6 @@ bool Log_to_csv_event_handler::
|
|||||||
table->field[field_index]->set_default();
|
table->field[field_index]->set_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* log table entries are not replicated */
|
|
||||||
if (table->file->ha_write_row(table->record[0]))
|
if (table->file->ha_write_row(table->record[0]))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@@ -827,7 +828,6 @@ err:
|
|||||||
if (need_close)
|
if (need_close)
|
||||||
close_log_table(thd, &open_tables_backup);
|
close_log_table(thd, &open_tables_backup);
|
||||||
|
|
||||||
thd->variables.option_bits= save_thd_options;
|
|
||||||
thd->time_zone_used= save_time_zone_used;
|
thd->time_zone_used= save_time_zone_used;
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
@@ -880,7 +880,6 @@ bool Log_to_csv_event_handler::
|
|||||||
ulong lock_time= (ulong) MY_MIN(lock_utime/1000000, TIME_MAX_VALUE_SECONDS);
|
ulong lock_time= (ulong) MY_MIN(lock_utime/1000000, TIME_MAX_VALUE_SECONDS);
|
||||||
ulong query_time_micro= (ulong) (query_utime % 1000000);
|
ulong query_time_micro= (ulong) (query_utime % 1000000);
|
||||||
ulong lock_time_micro= (ulong) (lock_utime % 1000000);
|
ulong lock_time_micro= (ulong) (lock_utime % 1000000);
|
||||||
|
|
||||||
DBUG_ENTER("Log_to_csv_event_handler::log_slow");
|
DBUG_ENTER("Log_to_csv_event_handler::log_slow");
|
||||||
|
|
||||||
thd->push_internal_handler(& error_handler);
|
thd->push_internal_handler(& error_handler);
|
||||||
@@ -997,7 +996,6 @@ bool Log_to_csv_event_handler::
|
|||||||
0, TRUE))
|
0, TRUE))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* log table entries are not replicated */
|
|
||||||
if (table->file->ha_write_row(table->record[0]))
|
if (table->file->ha_write_row(table->record[0]))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@@ -1982,7 +1980,7 @@ binlog_truncate_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all)
|
|||||||
if (cache_mngr->trx_cache.has_incident())
|
if (cache_mngr->trx_cache.has_incident())
|
||||||
error= mysql_bin_log.write_incident(thd);
|
error= mysql_bin_log.write_incident(thd);
|
||||||
|
|
||||||
thd->clear_binlog_table_maps();
|
thd->reset_binlog_for_next_statement();
|
||||||
|
|
||||||
cache_mngr->reset(false, true);
|
cache_mngr->reset(false, true);
|
||||||
}
|
}
|
||||||
@@ -2253,6 +2251,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
|
|||||||
we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid()
|
we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid()
|
||||||
*/
|
*/
|
||||||
cache_mngr->reset(false, true);
|
cache_mngr->reset(false, true);
|
||||||
|
thd->reset_binlog_for_next_statement();
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
if (!wsrep_emulate_bin_log && mysql_bin_log.check_write_error(thd))
|
if (!wsrep_emulate_bin_log && mysql_bin_log.check_write_error(thd))
|
||||||
@@ -2297,6 +2296,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
|
|||||||
*/
|
*/
|
||||||
if (!all)
|
if (!all)
|
||||||
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
|
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
|
||||||
|
thd->reset_binlog_for_next_statement();
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
@@ -2478,14 +2478,14 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
When a SAVEPOINT is executed inside a stored function/trigger we force the
|
When a SAVEPOINT is executed inside a stored function/trigger we force the
|
||||||
pending event to be flushed with a STMT_END_F flag and clear the table maps
|
pending event to be flushed with a STMT_END_F flag and reset binlog
|
||||||
as well to ensure that following DMLs will have a clean state to start
|
as well to ensure that following DMLs will have a clean state to start
|
||||||
with. ROLLBACK inside a stored routine has to finalize possibly existing
|
with. ROLLBACK inside a stored routine has to finalize possibly existing
|
||||||
current row-based pending event with cleaning up table maps. That ensures
|
current row-based pending event with cleaning up table maps. That ensures
|
||||||
that following DMLs will have a clean state to start with.
|
that following DMLs will have a clean state to start with.
|
||||||
*/
|
*/
|
||||||
if (thd->in_sub_stmt)
|
if (thd->in_sub_stmt)
|
||||||
thd->clear_binlog_table_maps();
|
thd->reset_binlog_for_next_statement();
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@@ -5773,7 +5773,7 @@ binlog_cache_mngr *THD::binlog_setup_trx_data()
|
|||||||
We only update the saved position if the old one was undefined,
|
We only update the saved position if the old one was undefined,
|
||||||
the reason is that there are some cases (e.g., for CREATE-SELECT)
|
the reason is that there are some cases (e.g., for CREATE-SELECT)
|
||||||
where the position is saved twice (e.g., both in
|
where the position is saved twice (e.g., both in
|
||||||
select_create::prepare() and THD::binlog_write_table_map()) , but
|
select_create::prepare() and binlog_write_table_map()) , but
|
||||||
we should use the first. This means that calls to this function
|
we should use the first. This means that calls to this function
|
||||||
can be used to start the statement before the first table map
|
can be used to start the statement before the first table map
|
||||||
event, to include some extra events.
|
event, to include some extra events.
|
||||||
@@ -5900,45 +5900,149 @@ binlog_start_consistent_snapshot(handlerton *hton, THD *thd)
|
|||||||
DBUG_RETURN(err);
|
DBUG_RETURN(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepare all tables that are updated for row logging
|
||||||
|
|
||||||
|
Annotate events and table maps are written by binlog_write_table_maps()
|
||||||
|
*/
|
||||||
|
|
||||||
|
void THD::binlog_prepare_for_row_logging()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("THD::binlog_prepare_for_row_logging");
|
||||||
|
for (TABLE *table= open_tables ; table; table= table->next)
|
||||||
|
{
|
||||||
|
if (table->query_id == query_id && table->current_lock == F_WRLCK)
|
||||||
|
table->file->prepare_for_row_logging();
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write annnotated row event (the query) if needed
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool THD::binlog_write_annotated_row(Log_event_writer *writer)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
DBUG_ENTER("THD::binlog_write_annotated_row");
|
||||||
|
|
||||||
|
if (!(IF_WSREP(!wsrep_fragments_certified_for_stmt(this), true) &&
|
||||||
|
variables.binlog_annotate_row_events &&
|
||||||
|
query_length()))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
Annotate_rows_log_event anno(this, 0, false);
|
||||||
|
if (unlikely((error= writer->write(&anno))))
|
||||||
|
{
|
||||||
|
if (my_errno == EFBIG)
|
||||||
|
writer->set_incident();
|
||||||
|
DBUG_RETURN(error);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write table map events for all tables that are using row logging.
|
||||||
|
This includes all tables used by this statement, including tables
|
||||||
|
used in triggers.
|
||||||
|
|
||||||
|
Also write annotate events and start transactions.
|
||||||
|
This is using the "tables_with_row_logging" list prepared by
|
||||||
|
THD::binlog_prepare_for_row_logging
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool THD::binlog_write_table_maps()
|
||||||
|
{
|
||||||
|
bool with_annotate;
|
||||||
|
MYSQL_LOCK *locks[2], **locks_end= locks;
|
||||||
|
DBUG_ENTER("THD::binlog_write_table_maps");
|
||||||
|
|
||||||
|
DBUG_ASSERT(!binlog_table_maps);
|
||||||
|
DBUG_ASSERT(is_current_stmt_binlog_format_row());
|
||||||
|
|
||||||
|
/* Initialize cache_mngr once per statement */
|
||||||
|
binlog_start_trans_and_stmt();
|
||||||
|
with_annotate= 1; // Write annotate with first map
|
||||||
|
|
||||||
|
if ((*locks_end= extra_lock))
|
||||||
|
locks_end++;
|
||||||
|
if ((*locks_end= lock))
|
||||||
|
locks_end++;
|
||||||
|
|
||||||
|
for (MYSQL_LOCK **cur_lock= locks ; cur_lock < locks_end ; cur_lock++)
|
||||||
|
{
|
||||||
|
TABLE **const end_ptr= (*cur_lock)->table + (*cur_lock)->table_count;
|
||||||
|
for (TABLE **table_ptr= (*cur_lock)->table;
|
||||||
|
table_ptr != end_ptr ;
|
||||||
|
++table_ptr)
|
||||||
|
{
|
||||||
|
TABLE *table= *table_ptr;
|
||||||
|
bool restore= 0;
|
||||||
|
/*
|
||||||
|
We have to also write table maps for tables that have not yet been
|
||||||
|
used, like for tables in after triggers
|
||||||
|
*/
|
||||||
|
if (!table->file->row_logging &&
|
||||||
|
table->query_id != query_id && table->current_lock == F_WRLCK)
|
||||||
|
{
|
||||||
|
if (table->file->prepare_for_row_logging())
|
||||||
|
restore= 1;
|
||||||
|
}
|
||||||
|
if (table->file->row_logging)
|
||||||
|
{
|
||||||
|
if (binlog_write_table_map(table, with_annotate))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
with_annotate= 0;
|
||||||
|
}
|
||||||
|
if (restore)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Restore original setting so that it doesn't cause problem for the
|
||||||
|
next statement
|
||||||
|
*/
|
||||||
|
table->file->row_logging= table->file->row_logging_init= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binlog_table_maps= 1; // Table maps written
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function writes a table map to the binary log.
|
This function writes a table map to the binary log.
|
||||||
Note that in order to keep the signature uniform with related methods,
|
Note that in order to keep the signature uniform with related methods,
|
||||||
we use a redundant parameter to indicate whether a transactional table
|
we use a redundant parameter to indicate whether a transactional table
|
||||||
was changed or not.
|
was changed or not.
|
||||||
|
|
||||||
If with_annotate != NULL and
|
|
||||||
*with_annotate = TRUE write also Annotate_rows before the table map.
|
|
||||||
|
|
||||||
@param table a pointer to the table.
|
@param table a pointer to the table.
|
||||||
@param is_transactional @c true indicates a transactional table,
|
@param with_annotate If true call binlog_write_annotated_row()
|
||||||
otherwise @c false a non-transactional.
|
|
||||||
@return
|
@return
|
||||||
nonzero if an error pops up when writing the table map event.
|
nonzero if an error pops up when writing the table map event.
|
||||||
*/
|
*/
|
||||||
int THD::binlog_write_table_map(TABLE *table, bool is_transactional,
|
|
||||||
bool *with_annotate)
|
bool THD::binlog_write_table_map(TABLE *table, bool with_annotate)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
bool is_transactional= table->file->row_logging_has_trans;
|
||||||
DBUG_ENTER("THD::binlog_write_table_map");
|
DBUG_ENTER("THD::binlog_write_table_map");
|
||||||
DBUG_PRINT("enter", ("table: %p (%s: #%lu)",
|
DBUG_PRINT("enter", ("table: %p (%s: #%lu)",
|
||||||
table, table->s->table_name.str,
|
table, table->s->table_name.str,
|
||||||
table->s->table_map_id));
|
table->s->table_map_id));
|
||||||
|
|
||||||
|
/* Pre-conditions */
|
||||||
|
DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
|
||||||
|
|
||||||
/* Ensure that all events in a GTID group are in the same cache */
|
/* Ensure that all events in a GTID group are in the same cache */
|
||||||
if (variables.option_bits & OPTION_GTID_BEGIN)
|
if (variables.option_bits & OPTION_GTID_BEGIN)
|
||||||
is_transactional= 1;
|
is_transactional= 1;
|
||||||
|
|
||||||
/* Pre-conditions */
|
|
||||||
DBUG_ASSERT(is_current_stmt_binlog_format_row());
|
|
||||||
DBUG_ASSERT(WSREP_EMULATE_BINLOG_NNULL(this) || mysql_bin_log.is_open());
|
|
||||||
DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
|
|
||||||
|
|
||||||
Table_map_log_event
|
Table_map_log_event
|
||||||
the_event(this, table, table->s->table_map_id, is_transactional);
|
the_event(this, table, table->s->table_map_id, is_transactional);
|
||||||
|
|
||||||
if (binlog_table_maps == 0)
|
|
||||||
binlog_start_trans_and_stmt();
|
|
||||||
|
|
||||||
binlog_cache_mngr *const cache_mngr=
|
binlog_cache_mngr *const cache_mngr=
|
||||||
(binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
|
(binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
|
||||||
binlog_cache_data *cache_data= (cache_mngr->
|
binlog_cache_data *cache_data= (cache_mngr->
|
||||||
@@ -5946,25 +6050,17 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional,
|
|||||||
IO_CACHE *file= &cache_data->cache_log;
|
IO_CACHE *file= &cache_data->cache_log;
|
||||||
Log_event_writer writer(file, cache_data);
|
Log_event_writer writer(file, cache_data);
|
||||||
|
|
||||||
if (with_annotate && *with_annotate)
|
if (with_annotate)
|
||||||
{
|
if (binlog_write_annotated_row(&writer))
|
||||||
Annotate_rows_log_event anno(table->in_use, is_transactional, false);
|
DBUG_RETURN(1);
|
||||||
/* Annotate event should be written not more than once */
|
|
||||||
*with_annotate= 0;
|
|
||||||
if (unlikely((error= writer.write(&anno))))
|
|
||||||
{
|
|
||||||
if (my_errno == EFBIG)
|
|
||||||
cache_data->set_incident();
|
|
||||||
DBUG_RETURN(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (unlikely((error= writer.write(&the_event))))
|
if (unlikely((error= writer.write(&the_event))))
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
|
|
||||||
binlog_table_maps++;
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function retrieves a pending row event from a cache which is
|
This function retrieves a pending row event from a cache which is
|
||||||
specified through the parameter @c is_transactional. Respectively, when it
|
specified through the parameter @c is_transactional. Respectively, when it
|
||||||
@@ -10848,7 +10944,7 @@ void wsrep_thd_binlog_trx_reset(THD * thd)
|
|||||||
cache_mngr->stmt_cache.reset();
|
cache_mngr->stmt_cache.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thd->clear_binlog_table_maps();
|
thd->reset_binlog_for_next_statement();
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10875,7 +10971,6 @@ bool wsrep_stmt_rollback_is_safe(THD* thd)
|
|||||||
binlog_cache_mngr *cache_mngr=
|
binlog_cache_mngr *cache_mngr=
|
||||||
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
|
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
|
||||||
|
|
||||||
|
|
||||||
if (binlog_hton && cache_mngr)
|
if (binlog_hton && cache_mngr)
|
||||||
{
|
{
|
||||||
binlog_cache_data * trx_cache = &cache_mngr->trx_cache;
|
binlog_cache_data * trx_cache = &cache_mngr->trx_cache;
|
||||||
|
@@ -1144,6 +1144,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
|
|||||||
|
|
||||||
void make_default_log_name(char **out, const char* log_ext, bool once);
|
void make_default_log_name(char **out, const char* log_ext, bool once);
|
||||||
void binlog_reset_cache(THD *thd);
|
void binlog_reset_cache(THD *thd);
|
||||||
|
bool write_annotated_row(THD *thd);
|
||||||
|
|
||||||
extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
|
extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
|
||||||
extern handlerton *binlog_hton;
|
extern handlerton *binlog_hton;
|
||||||
|
@@ -942,6 +942,7 @@ public:
|
|||||||
int write_footer();
|
int write_footer();
|
||||||
my_off_t pos() { return my_b_safe_tell(file); }
|
my_off_t pos() { return my_b_safe_tell(file); }
|
||||||
void add_status(enum_logged_status status);
|
void add_status(enum_logged_status status);
|
||||||
|
void set_incident();
|
||||||
|
|
||||||
Log_event_writer(IO_CACHE *file_arg, binlog_cache_data *cache_data_arg,
|
Log_event_writer(IO_CACHE *file_arg, binlog_cache_data *cache_data_arg,
|
||||||
Binlog_crypt_data *cr= 0)
|
Binlog_crypt_data *cr= 0)
|
||||||
|
@@ -799,7 +799,10 @@ my_bool Log_event::need_checksum()
|
|||||||
int Log_event_writer::write_internal(const uchar *pos, size_t len)
|
int Log_event_writer::write_internal(const uchar *pos, size_t len)
|
||||||
{
|
{
|
||||||
if (my_b_safe_write(file, pos, len))
|
if (my_b_safe_write(file, pos, len))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("error", ("write to log failed: %d", my_errno));
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
bytes_written+= len;
|
bytes_written+= len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -6153,13 +6156,10 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
|
|||||||
(tbl->s->db.str[tbl->s->db.length] == 0));
|
(tbl->s->db.str[tbl->s->db.length] == 0));
|
||||||
DBUG_ASSERT(tbl->s->table_name.str[tbl->s->table_name.length] == 0);
|
DBUG_ASSERT(tbl->s->table_name.str[tbl->s->table_name.length] == 0);
|
||||||
|
|
||||||
#ifdef MYSQL_SERVER
|
|
||||||
binlog_type_info_array= (Binlog_type_info *)thd->alloc(m_table->s->fields *
|
binlog_type_info_array= (Binlog_type_info *)thd->alloc(m_table->s->fields *
|
||||||
sizeof(Binlog_type_info));
|
sizeof(Binlog_type_info));
|
||||||
for (uint i= 0; i < m_table->s->fields; i++)
|
for (uint i= 0; i < m_table->s->fields; i++)
|
||||||
binlog_type_info_array[i]= m_table->field[i]->binlog_type_info();
|
binlog_type_info_array[i]= m_table->field[i]->binlog_type_info();
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
m_data_size= TABLE_MAP_HEADER_LEN;
|
m_data_size= TABLE_MAP_HEADER_LEN;
|
||||||
DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", m_data_size= 6;);
|
DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", m_data_size= 6;);
|
||||||
@@ -7079,14 +7079,14 @@ bool Rows_log_event::process_triggers(trg_event_type event,
|
|||||||
m_table->triggers->mark_fields_used(event);
|
m_table->triggers->mark_fields_used(event);
|
||||||
if (slave_run_triggers_for_rbr == SLAVE_RUN_TRIGGERS_FOR_RBR_YES)
|
if (slave_run_triggers_for_rbr == SLAVE_RUN_TRIGGERS_FOR_RBR_YES)
|
||||||
{
|
{
|
||||||
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
|
|
||||||
result= m_table->triggers->process_triggers(thd, event,
|
result= m_table->triggers->process_triggers(thd, event,
|
||||||
time_type, old_row_is_record1);
|
time_type,
|
||||||
reenable_binlog(thd);
|
old_row_is_record1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result= m_table->triggers->process_triggers(thd, event,
|
result= m_table->triggers->process_triggers(thd, event,
|
||||||
time_type, old_row_is_record1);
|
time_type,
|
||||||
|
old_row_is_record1);
|
||||||
|
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
@@ -423,10 +423,12 @@ rpl_slave_state::truncate_state_table(THD *thd)
|
|||||||
TABLE_LIST tlist;
|
TABLE_LIST tlist;
|
||||||
int err= 0;
|
int err= 0;
|
||||||
|
|
||||||
tmp_disable_binlog(thd);
|
tlist.init_one_table(&MYSQL_SCHEMA_NAME, &rpl_gtid_slave_state_table_name,
|
||||||
tlist.init_one_table(&MYSQL_SCHEMA_NAME, &rpl_gtid_slave_state_table_name, NULL, TL_WRITE);
|
NULL, TL_WRITE);
|
||||||
if (!(err= open_and_lock_tables(thd, &tlist, FALSE, 0)))
|
if (!(err= open_and_lock_tables(thd, &tlist, FALSE,
|
||||||
|
MYSQL_OPEN_IGNORE_LOGGING_FORMAT)))
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(!tlist.table->file->row_logging);
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, "mysql",
|
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, "mysql",
|
||||||
rpl_gtid_slave_state_table_name.str);
|
rpl_gtid_slave_state_table_name.str);
|
||||||
err= tlist.table->file->ha_truncate();
|
err= tlist.table->file->ha_truncate();
|
||||||
@@ -445,8 +447,6 @@ rpl_slave_state::truncate_state_table(THD *thd)
|
|||||||
}
|
}
|
||||||
thd->mdl_context.release_transactional_locks();
|
thd->mdl_context.release_transactional_locks();
|
||||||
}
|
}
|
||||||
|
|
||||||
reenable_binlog(thd);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,6 +676,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
|
|||||||
table_opened= true;
|
table_opened= true;
|
||||||
table= tlist.table;
|
table= tlist.table;
|
||||||
hton= table->s->db_type();
|
hton= table->s->db_type();
|
||||||
|
table->file->row_logging= 0; // No binary logging
|
||||||
|
|
||||||
if ((err= gtid_check_rpl_slave_state_table(table)))
|
if ((err= gtid_check_rpl_slave_state_table(table)))
|
||||||
goto end;
|
goto end;
|
||||||
|
@@ -100,6 +100,7 @@ int injector::transaction::commit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TO_BE_DELETED
|
||||||
int injector::transaction::use_table(server_id_type sid, table tbl)
|
int injector::transaction::use_table(server_id_type sid, table tbl)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("injector::transaction::use_table");
|
DBUG_ENTER("injector::transaction::use_table");
|
||||||
@@ -111,12 +112,12 @@ int injector::transaction::use_table(server_id_type sid, table tbl)
|
|||||||
|
|
||||||
server_id_type save_id= m_thd->variables.server_id;
|
server_id_type save_id= m_thd->variables.server_id;
|
||||||
m_thd->set_server_id(sid);
|
m_thd->set_server_id(sid);
|
||||||
error= m_thd->binlog_write_table_map(tbl.get_table(),
|
DBUG_ASSERT(tbl.is_transactional() == tbl.get_table()->file->row_logging_has_trans);
|
||||||
tbl.is_transactional());
|
error= m_thd->binlog_write_table_map(tbl.get_table(), 0);
|
||||||
m_thd->set_server_id(save_id);
|
m_thd->set_server_id(save_id);
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
injector::transaction::binlog_pos injector::transaction::start_pos() const
|
injector::transaction::binlog_pos injector::transaction::start_pos() const
|
||||||
|
@@ -177,8 +177,9 @@ public:
|
|||||||
>0 Failure
|
>0 Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
#ifdef TO_BE_DELETED
|
||||||
int use_table(server_id_type sid, table tbl);
|
int use_table(server_id_type sid, table tbl);
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
Commit a transaction.
|
Commit a transaction.
|
||||||
|
|
||||||
|
23
sql/slave.cc
23
sql/slave.cc
@@ -3582,20 +3582,19 @@ void set_slave_thread_options(THD* thd)
|
|||||||
when max_join_size is 4G, OPTION_BIG_SELECTS is automatically set, but
|
when max_join_size is 4G, OPTION_BIG_SELECTS is automatically set, but
|
||||||
only for client threads.
|
only for client threads.
|
||||||
*/
|
*/
|
||||||
ulonglong options= thd->variables.option_bits | OPTION_BIG_SELECTS;
|
ulonglong options= (thd->variables.option_bits |
|
||||||
if (opt_log_slave_updates)
|
OPTION_BIG_SELECTS | OPTION_BIN_LOG);
|
||||||
options|= OPTION_BIN_LOG;
|
if (!opt_log_slave_updates)
|
||||||
else
|
|
||||||
options&= ~OPTION_BIN_LOG;
|
options&= ~OPTION_BIN_LOG;
|
||||||
thd->variables.option_bits= options;
|
|
||||||
thd->variables.completion_type= 0;
|
|
||||||
|
|
||||||
/* For easier test in LOGGER::log_command */
|
/* For easier test in LOGGER::log_command */
|
||||||
if (thd->variables.log_disabled_statements & LOG_DISABLE_SLAVE)
|
if (thd->variables.log_disabled_statements & LOG_DISABLE_SLAVE)
|
||||||
thd->variables.option_bits|= OPTION_LOG_OFF;
|
options|= OPTION_LOG_OFF;
|
||||||
|
thd->variables.option_bits= options;
|
||||||
|
|
||||||
thd->variables.sql_log_slow= !MY_TEST(thd->variables.log_slow_disabled_statements &
|
thd->variables.completion_type= 0;
|
||||||
LOG_SLOW_DISABLE_SLAVE);
|
thd->variables.sql_log_slow=
|
||||||
|
!MY_TEST(thd->variables.log_slow_disabled_statements &
|
||||||
|
LOG_SLOW_DISABLE_SLAVE);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8196,7 +8195,7 @@ void Rows_event_tracker::reset()
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Update log event tracking data.
|
Update log event tracking data.
|
||||||
|
|
||||||
The first- and last- seen event binlog position get memorized, as
|
The first- and last- seen event binlog position get memorized, as
|
||||||
well as the end-of-statement status of the last one.
|
well as the end-of-statement status of the last one.
|
||||||
@@ -8206,6 +8205,7 @@ void Rows_event_tracker::update(const char* file_name, my_off_t pos,
|
|||||||
const char* buf,
|
const char* buf,
|
||||||
const Format_description_log_event *fdle)
|
const Format_description_log_event *fdle)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Rows_event_tracker::update");
|
||||||
if (!first_seen)
|
if (!first_seen)
|
||||||
{
|
{
|
||||||
first_seen= pos;
|
first_seen= pos;
|
||||||
@@ -8214,6 +8214,7 @@ void Rows_event_tracker::update(const char* file_name, my_off_t pos,
|
|||||||
last_seen= pos;
|
last_seen= pos;
|
||||||
DBUG_ASSERT(stmt_end_seen == 0); // We can only have one
|
DBUG_ASSERT(stmt_end_seen == 0); // We can only have one
|
||||||
stmt_end_seen= get_row_event_stmt_end(buf, fdle);
|
stmt_end_seen= get_row_event_stmt_end(buf, fdle);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1942,7 +1942,9 @@ class Grant_tables
|
|||||||
if (res)
|
if (res)
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
if (lock_tables(thd, first, counter, MYSQL_LOCK_IGNORE_TIMEOUT))
|
if (lock_tables(thd, first, counter,
|
||||||
|
MYSQL_LOCK_IGNORE_TIMEOUT |
|
||||||
|
MYSQL_OPEN_IGNORE_LOGGING_FORMAT))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
p_user_table->set_table(tables[USER_TABLE].table);
|
p_user_table->set_table(tables[USER_TABLE].table);
|
||||||
@@ -4397,7 +4399,8 @@ static USER_AUTH auth_no_password;
|
|||||||
|
|
||||||
static int replace_user_table(THD *thd, const User_table &user_table,
|
static int replace_user_table(THD *thd, const User_table &user_table,
|
||||||
LEX_USER * const combo, privilege_t rights,
|
LEX_USER * const combo, privilege_t rights,
|
||||||
const bool revoke_grant, const bool can_create_user,
|
const bool revoke_grant,
|
||||||
|
const bool can_create_user,
|
||||||
const bool no_auto_create)
|
const bool no_auto_create)
|
||||||
{
|
{
|
||||||
int error = -1;
|
int error = -1;
|
||||||
@@ -5426,6 +5429,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
|
|||||||
|
|
||||||
List_iterator <LEX_COLUMN> iter(columns);
|
List_iterator <LEX_COLUMN> iter(columns);
|
||||||
class LEX_COLUMN *column;
|
class LEX_COLUMN *column;
|
||||||
|
|
||||||
int error= table->file->ha_index_init(0, 1);
|
int error= table->file->ha_index_init(0, 1);
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
{
|
{
|
||||||
@@ -5776,7 +5780,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
restore_record(table, s->default_values); // Get empty record
|
restore_record(table, s->default_values); // Get empty record
|
||||||
table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
|
table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
|
||||||
table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
|
table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
|
||||||
table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
|
table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
|
||||||
|
@@ -1027,9 +1027,7 @@ send_result_message:
|
|||||||
*save_next_global= table->next_global;
|
*save_next_global= table->next_global;
|
||||||
table->next_local= table->next_global= 0;
|
table->next_local= table->next_global= 0;
|
||||||
|
|
||||||
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
|
||||||
result_code= admin_recreate_table(thd, table);
|
result_code= admin_recreate_table(thd, table);
|
||||||
reenable_binlog(thd);
|
|
||||||
trans_commit_stmt(thd);
|
trans_commit_stmt(thd);
|
||||||
trans_commit(thd);
|
trans_commit(thd);
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
|
@@ -734,8 +734,9 @@ bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection)
|
|||||||
Clear 'check_table_binlog_row_based_done' flag. For tables which were used
|
Clear 'check_table_binlog_row_based_done' flag. For tables which were used
|
||||||
by current substatement the flag is cleared as part of 'ha_reset()' call.
|
by current substatement the flag is cleared as part of 'ha_reset()' call.
|
||||||
For the rest of the open tables not used by current substament if this
|
For the rest of the open tables not used by current substament if this
|
||||||
flag is enabled as part of current substatement execution, clear the flag
|
flag is enabled as part of current substatement execution,
|
||||||
explicitly.
|
(for example when THD::binlog_write_table_maps() calls
|
||||||
|
prepare_for_row_logging()), clear the flag explicitly.
|
||||||
|
|
||||||
NOTE
|
NOTE
|
||||||
The reason we reset query_id is that it's not enough to just test
|
The reason we reset query_id is that it's not enough to just test
|
||||||
@@ -759,7 +760,7 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table)
|
|||||||
table->query_id= 0;
|
table->query_id= 0;
|
||||||
table->file->ha_reset();
|
table->file->ha_reset();
|
||||||
}
|
}
|
||||||
else if (table->file->check_table_binlog_row_based_done)
|
else
|
||||||
table->file->clear_cached_table_binlog_row_based_flag();
|
table->file->clear_cached_table_binlog_row_based_flag();
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@@ -1660,9 +1661,10 @@ static int set_partitions_as_used(TABLE_LIST *tl, TABLE *t)
|
|||||||
needed to remedy problem before retrying again.
|
needed to remedy problem before retrying again.
|
||||||
@retval FALSE 't' was not locked, not a VIEW or an error happened.
|
@retval FALSE 't' was not locked, not a VIEW or an error happened.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool is_locked_view(THD *thd, TABLE_LIST *t)
|
bool is_locked_view(THD *thd, TABLE_LIST *t)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("check_locked_view");
|
DBUG_ENTER("is_locked_view");
|
||||||
/*
|
/*
|
||||||
Is this table a view and not a base table?
|
Is this table a view and not a base table?
|
||||||
(it is work around to allow to open view with locked tables,
|
(it is work around to allow to open view with locked tables,
|
||||||
@@ -2212,8 +2214,8 @@ retry_share:
|
|||||||
my_error(ER_NOT_SEQUENCE, MYF(0), table_list->db.str, table_list->alias.str);
|
my_error(ER_NOT_SEQUENCE, MYF(0), table_list->db.str, table_list->alias.str);
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
table->init(thd, table_list);
|
table->init(thd, table_list);
|
||||||
|
DBUG_ASSERT(thd->locked_tables_mode || table->file->row_logging == 0);
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
@@ -3738,10 +3740,11 @@ open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags,
|
|||||||
temporary table or SEQUENCE (see sequence_insert()).
|
temporary table or SEQUENCE (see sequence_insert()).
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(is_temporary_table(tables) || tables->table->s->sequence);
|
DBUG_ASSERT(is_temporary_table(tables) || tables->table->s->sequence);
|
||||||
if (tables->sequence && tables->table->s->table_type != TABLE_TYPE_SEQUENCE)
|
if (tables->sequence &&
|
||||||
|
tables->table->s->table_type != TABLE_TYPE_SEQUENCE)
|
||||||
{
|
{
|
||||||
my_error(ER_NOT_SEQUENCE, MYF(0), tables->db.str, tables->alias.str);
|
my_error(ER_NOT_SEQUENCE, MYF(0), tables->db.str, tables->alias.str);
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tables->open_type == OT_TEMPORARY_ONLY)
|
else if (tables->open_type == OT_TEMPORARY_ONLY)
|
||||||
@@ -5214,7 +5217,9 @@ bool open_and_lock_tables(THD *thd, const DDL_options_st &options,
|
|||||||
if (lock_tables(thd, tables, counter, flags))
|
if (lock_tables(thd, tables, counter, flags))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
(void) read_statistics_for_tables_if_needed(thd, tables);
|
/* Don't read statistics tables when opening internal tables */
|
||||||
|
if (!(flags & MYSQL_OPEN_IGNORE_LOGGING_FORMAT))
|
||||||
|
(void) read_statistics_for_tables_if_needed(thd, tables);
|
||||||
|
|
||||||
if (derived)
|
if (derived)
|
||||||
{
|
{
|
||||||
@@ -5348,12 +5353,19 @@ bool open_tables_only_view_structure(THD *thd, TABLE_LIST *table_list,
|
|||||||
static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table_list)
|
static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table_list)
|
||||||
{
|
{
|
||||||
TABLE_LIST *table;
|
TABLE_LIST *table;
|
||||||
|
DBUG_ENTER("mark_real_tables_as_free_for_reuse");
|
||||||
|
|
||||||
|
/*
|
||||||
|
We have to make two loops as HA_EXTRA_DETACH_CHILDREN may
|
||||||
|
remove items from the table list that we have to reset
|
||||||
|
*/
|
||||||
for (table= table_list; table; table= table->next_global)
|
for (table= table_list; table; table= table->next_global)
|
||||||
|
{
|
||||||
if (!table->placeholder())
|
if (!table->placeholder())
|
||||||
{
|
|
||||||
table->table->query_id= 0;
|
table->table->query_id= 0;
|
||||||
}
|
}
|
||||||
for (table= table_list; table; table= table->next_global)
|
for (table= table_list; table; table= table->next_global)
|
||||||
|
{
|
||||||
if (!table->placeholder())
|
if (!table->placeholder())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -5364,6 +5376,8 @@ static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table_list)
|
|||||||
*/
|
*/
|
||||||
table->table->file->extra(HA_EXTRA_DETACH_CHILDREN);
|
table->table->file->extra(HA_EXTRA_DETACH_CHILDREN);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5428,7 +5442,7 @@ err:
|
|||||||
|
|
||||||
bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
||||||
{
|
{
|
||||||
TABLE_LIST *table;
|
TABLE_LIST *table, *first_not_own;
|
||||||
DBUG_ENTER("lock_tables");
|
DBUG_ENTER("lock_tables");
|
||||||
/*
|
/*
|
||||||
We can't meet statement requiring prelocking if we already
|
We can't meet statement requiring prelocking if we already
|
||||||
@@ -5438,7 +5452,9 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
|||||||
!thd->lex->requires_prelocking());
|
!thd->lex->requires_prelocking());
|
||||||
|
|
||||||
if (!tables && !thd->lex->requires_prelocking())
|
if (!tables && !thd->lex->requires_prelocking())
|
||||||
DBUG_RETURN(thd->decide_logging_format(tables));
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
first_not_own= thd->lex->first_not_own_table();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check for thd->locked_tables_mode to avoid a redundant
|
Check for thd->locked_tables_mode to avoid a redundant
|
||||||
@@ -5454,13 +5470,26 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
||||||
TABLE **start,**ptr;
|
TABLE **start,**ptr;
|
||||||
|
bool found_first_not_own= 0;
|
||||||
|
|
||||||
if (!(ptr=start=(TABLE**) thd->alloc(sizeof(TABLE*)*count)))
|
if (!(ptr=start=(TABLE**) thd->alloc(sizeof(TABLE*)*count)))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Collect changes tables for table lock.
|
||||||
|
Mark own tables with query id as this is needed by
|
||||||
|
prepare_for_row_logging()
|
||||||
|
*/
|
||||||
for (table= tables; table; table= table->next_global)
|
for (table= tables; table; table= table->next_global)
|
||||||
{
|
{
|
||||||
|
if (table == first_not_own)
|
||||||
|
found_first_not_own= 1;
|
||||||
if (!table->placeholder())
|
if (!table->placeholder())
|
||||||
*(ptr++)= table->table;
|
{
|
||||||
|
*(ptr++)= table->table;
|
||||||
|
if (!found_first_not_own)
|
||||||
|
table->table->query_id= thd->query_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_SYNC(thd, "before_lock_tables_takes_lock");
|
DEBUG_SYNC(thd, "before_lock_tables_takes_lock");
|
||||||
@@ -5474,7 +5503,6 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
|||||||
if (thd->lex->requires_prelocking() &&
|
if (thd->lex->requires_prelocking() &&
|
||||||
thd->lex->sql_command != SQLCOM_LOCK_TABLES)
|
thd->lex->sql_command != SQLCOM_LOCK_TABLES)
|
||||||
{
|
{
|
||||||
TABLE_LIST *first_not_own= thd->lex->first_not_own_table();
|
|
||||||
/*
|
/*
|
||||||
We just have done implicit LOCK TABLES, and now we have
|
We just have done implicit LOCK TABLES, and now we have
|
||||||
to emulate first open_and_lock_tables() after it.
|
to emulate first open_and_lock_tables() after it.
|
||||||
@@ -5492,7 +5520,6 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
|||||||
{
|
{
|
||||||
if (!table->placeholder())
|
if (!table->placeholder())
|
||||||
{
|
{
|
||||||
table->table->query_id= thd->query_id;
|
|
||||||
if (check_lock_and_start_stmt(thd, thd->lex, table))
|
if (check_lock_and_start_stmt(thd, thd->lex, table))
|
||||||
{
|
{
|
||||||
mysql_unlock_tables(thd, thd->lock);
|
mysql_unlock_tables(thd, thd->lock);
|
||||||
@@ -5512,7 +5539,6 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TABLE_LIST *first_not_own= thd->lex->first_not_own_table();
|
|
||||||
/*
|
/*
|
||||||
When open_and_lock_tables() is called for a single table out of
|
When open_and_lock_tables() is called for a single table out of
|
||||||
a table list, the 'next_global' chain is temporarily broken. We
|
a table list, the 'next_global' chain is temporarily broken. We
|
||||||
@@ -5528,6 +5554,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
|||||||
if (table->placeholder())
|
if (table->placeholder())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
table->table->query_id= thd->query_id;
|
||||||
/*
|
/*
|
||||||
In a stored function or trigger we should ensure that we won't change
|
In a stored function or trigger we should ensure that we won't change
|
||||||
a table that is already used by the calling statement.
|
a table that is already used by the calling statement.
|
||||||
@@ -5567,7 +5594,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool res= fix_all_session_vcol_exprs(thd, tables);
|
bool res= fix_all_session_vcol_exprs(thd, tables);
|
||||||
if (!res)
|
if (!res && !(flags & MYSQL_OPEN_IGNORE_LOGGING_FORMAT))
|
||||||
res= thd->decide_logging_format(tables);
|
res= thd->decide_logging_format(tables);
|
||||||
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
@@ -9005,6 +9032,7 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,
|
|||||||
*/
|
*/
|
||||||
if (open_and_lock_tables(thd, table_list, FALSE,
|
if (open_and_lock_tables(thd, table_list, FALSE,
|
||||||
(MYSQL_OPEN_IGNORE_FLUSH |
|
(MYSQL_OPEN_IGNORE_FLUSH |
|
||||||
|
MYSQL_OPEN_IGNORE_LOGGING_FORMAT |
|
||||||
(table_list->lock_type < TL_WRITE_ALLOW_WRITE ?
|
(table_list->lock_type < TL_WRITE_ALLOW_WRITE ?
|
||||||
MYSQL_LOCK_IGNORE_TIMEOUT : 0))))
|
MYSQL_LOCK_IGNORE_TIMEOUT : 0))))
|
||||||
{
|
{
|
||||||
@@ -9016,6 +9044,7 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,
|
|||||||
for (TABLE_LIST *tables= table_list; tables; tables= tables->next_global)
|
for (TABLE_LIST *tables= table_list; tables; tables= tables->next_global)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(tables->table->s->table_category == TABLE_CATEGORY_SYSTEM);
|
DBUG_ASSERT(tables->table->s->table_category == TABLE_CATEGORY_SYSTEM);
|
||||||
|
tables->table->file->row_logging= 0;
|
||||||
tables->table->use_all_columns();
|
tables->table->use_all_columns();
|
||||||
}
|
}
|
||||||
lex->restore_backup_query_tables_list(&query_tables_list_backup);
|
lex->restore_backup_query_tables_list(&query_tables_list_backup);
|
||||||
@@ -9103,8 +9132,9 @@ open_system_table_for_update(THD *thd, TABLE_LIST *one_table)
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM);
|
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM);
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
|
/* This table instance is not row logged */
|
||||||
|
table->file->row_logging= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(table);
|
DBUG_RETURN(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9137,6 +9167,8 @@ open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup)
|
|||||||
if ((table= open_ltable(thd, one_table, one_table->lock_type, flags)))
|
if ((table= open_ltable(thd, one_table, one_table->lock_type, flags)))
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_LOG);
|
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_LOG);
|
||||||
|
DBUG_ASSERT(!table->file->row_logging);
|
||||||
|
|
||||||
/* Make sure all columns get assigned to a default value */
|
/* Make sure all columns get assigned to a default value */
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
DBUG_ASSERT(table->s->no_replicate);
|
DBUG_ASSERT(table->s->no_replicate);
|
||||||
|
@@ -125,6 +125,11 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
|||||||
*/
|
*/
|
||||||
#define MYSQL_OPEN_IGNORE_REPAIR 0x10000
|
#define MYSQL_OPEN_IGNORE_REPAIR 0x10000
|
||||||
|
|
||||||
|
/**
|
||||||
|
Don't call decide_logging_format. Used for statistic tables etc
|
||||||
|
*/
|
||||||
|
#define MYSQL_OPEN_IGNORE_LOGGING_FORMAT 0x20000
|
||||||
|
|
||||||
/** Please refer to the internals manual. */
|
/** Please refer to the internals manual. */
|
||||||
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
|
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
|
||||||
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |\
|
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |\
|
||||||
|
@@ -636,7 +636,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
|
|||||||
m_current_stage_key(0), m_psi(0),
|
m_current_stage_key(0), m_psi(0),
|
||||||
in_sub_stmt(0), log_all_errors(0),
|
in_sub_stmt(0), log_all_errors(0),
|
||||||
binlog_unsafe_warning_flags(0),
|
binlog_unsafe_warning_flags(0),
|
||||||
binlog_table_maps(0),
|
|
||||||
bulk_param(0),
|
bulk_param(0),
|
||||||
table_map_for_update(0),
|
table_map_for_update(0),
|
||||||
m_examined_row_count(0),
|
m_examined_row_count(0),
|
||||||
@@ -797,6 +796,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
|
|||||||
bzero((void*) ha_data, sizeof(ha_data));
|
bzero((void*) ha_data, sizeof(ha_data));
|
||||||
mysys_var=0;
|
mysys_var=0;
|
||||||
binlog_evt_union.do_union= FALSE;
|
binlog_evt_union.do_union= FALSE;
|
||||||
|
binlog_table_maps= FALSE;
|
||||||
enable_slow_log= 0;
|
enable_slow_log= 0;
|
||||||
durability_property= HA_REGULAR_DURABILITY;
|
durability_property= HA_REGULAR_DURABILITY;
|
||||||
|
|
||||||
@@ -1315,8 +1315,6 @@ void THD::init()
|
|||||||
else
|
else
|
||||||
variables.option_bits&= ~OPTION_BIN_LOG;
|
variables.option_bits&= ~OPTION_BIN_LOG;
|
||||||
|
|
||||||
variables.sql_log_bin_off= 0;
|
|
||||||
|
|
||||||
select_commands= update_commands= other_commands= 0;
|
select_commands= update_commands= other_commands= 0;
|
||||||
/* Set to handle counting of aborted connections */
|
/* Set to handle counting of aborted connections */
|
||||||
userstat_running= opt_userstat_running;
|
userstat_running= opt_userstat_running;
|
||||||
@@ -5837,8 +5835,9 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("THD::decide_logging_format");
|
DBUG_ENTER("THD::decide_logging_format");
|
||||||
DBUG_PRINT("info", ("Query: %.*s", (uint) query_length(), query()));
|
DBUG_PRINT("info", ("Query: %.*s", (uint) query_length(), query()));
|
||||||
DBUG_PRINT("info", ("variables.binlog_format: %lu",
|
DBUG_PRINT("info", ("binlog_format: %lu", (ulong) variables.binlog_format));
|
||||||
variables.binlog_format));
|
DBUG_PRINT("info", ("current_stmt_binlog_format: %lu",
|
||||||
|
(ulong) current_stmt_binlog_format));
|
||||||
DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x",
|
DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x",
|
||||||
lex->get_stmt_unsafe_flags()));
|
lex->get_stmt_unsafe_flags()));
|
||||||
|
|
||||||
@@ -5861,18 +5860,14 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
if ((WSREP_EMULATE_BINLOG_NNULL(this) ||
|
if ((WSREP_EMULATE_BINLOG_NNULL(this) ||
|
||||||
(mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG))) &&
|
(mysql_bin_log.is_open() &&
|
||||||
|
(variables.option_bits & OPTION_BIN_LOG))) &&
|
||||||
!(wsrep_binlog_format() == BINLOG_FORMAT_STMT &&
|
!(wsrep_binlog_format() == BINLOG_FORMAT_STMT &&
|
||||||
!binlog_filter->db_ok(db.str)))
|
!binlog_filter->db_ok(db.str)))
|
||||||
#else
|
|
||||||
if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) &&
|
|
||||||
!(wsrep_binlog_format() == BINLOG_FORMAT_STMT &&
|
|
||||||
!binlog_filter->db_ok(db.str)))
|
|
||||||
#endif /* WITH_WSREP */
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (is_bulk_op())
|
if (is_bulk_op())
|
||||||
{
|
{
|
||||||
if (wsrep_binlog_format() == BINLOG_FORMAT_STMT)
|
if (wsrep_binlog_format() == BINLOG_FORMAT_STMT)
|
||||||
@@ -5915,6 +5910,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
bool has_auto_increment_write_tables_not_first= FALSE;
|
bool has_auto_increment_write_tables_not_first= FALSE;
|
||||||
bool found_first_not_own_table= FALSE;
|
bool found_first_not_own_table= FALSE;
|
||||||
bool has_write_tables_with_unsafe_statements= FALSE;
|
bool has_write_tables_with_unsafe_statements= FALSE;
|
||||||
|
bool blackhole_table_found= 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A pointer to a previous table that was changed.
|
A pointer to a previous table that was changed.
|
||||||
@@ -6040,6 +6036,10 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
if (prev_write_table && prev_write_table->file->ht !=
|
if (prev_write_table && prev_write_table->file->ht !=
|
||||||
table->file->ht)
|
table->file->ht)
|
||||||
multi_write_engine= TRUE;
|
multi_write_engine= TRUE;
|
||||||
|
|
||||||
|
if (table->file->ht->db_type == DB_TYPE_BLACKHOLE_DB)
|
||||||
|
blackhole_table_found= 1;
|
||||||
|
|
||||||
if (share->non_determinstic_insert &&
|
if (share->non_determinstic_insert &&
|
||||||
!(sql_command_flags[lex->sql_command] & CF_SCHEMA_CHANGE))
|
!(sql_command_flags[lex->sql_command] & CF_SCHEMA_CHANGE))
|
||||||
has_write_tables_with_unsafe_statements= true;
|
has_write_tables_with_unsafe_statements= true;
|
||||||
@@ -6285,7 +6285,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
is_current_stmt_binlog_format_row() ?
|
is_current_stmt_binlog_format_row() ?
|
||||||
"ROW" : "STATEMENT"));
|
"ROW" : "STATEMENT"));
|
||||||
|
|
||||||
if (variables.binlog_format == BINLOG_FORMAT_ROW &&
|
if (blackhole_table_found &&
|
||||||
|
variables.binlog_format == BINLOG_FORMAT_ROW &&
|
||||||
(sql_command_flags[lex->sql_command] &
|
(sql_command_flags[lex->sql_command] &
|
||||||
(CF_UPDATES_DATA | CF_DELETES_DATA)))
|
(CF_UPDATES_DATA | CF_DELETES_DATA)))
|
||||||
{
|
{
|
||||||
@@ -6301,8 +6302,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
if (table->table->file->ht->db_type == DB_TYPE_BLACKHOLE_DB &&
|
if (table->table->file->ht->db_type == DB_TYPE_BLACKHOLE_DB &&
|
||||||
table->lock_type >= TL_WRITE_ALLOW_WRITE)
|
table->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||||
{
|
{
|
||||||
table_names.append(&table->table_name);
|
table_names.append(&table->table_name);
|
||||||
table_names.append(",");
|
table_names.append(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!table_names.is_empty())
|
if (!table_names.is_empty())
|
||||||
@@ -6322,9 +6323,12 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
table_names.c_ptr());
|
table_names.c_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_write && is_current_stmt_binlog_format_row())
|
||||||
|
binlog_prepare_for_row_logging();
|
||||||
}
|
}
|
||||||
#ifndef DBUG_OFF
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DBUG_PRINT("info", ("decision: no logging since "
|
DBUG_PRINT("info", ("decision: no logging since "
|
||||||
"mysql_bin_log.is_open() = %d "
|
"mysql_bin_log.is_open() = %d "
|
||||||
"and (options & OPTION_BIN_LOG) = 0x%llx "
|
"and (options & OPTION_BIN_LOG) = 0x%llx "
|
||||||
@@ -6334,22 +6338,23 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
|||||||
(variables.option_bits & OPTION_BIN_LOG),
|
(variables.option_bits & OPTION_BIN_LOG),
|
||||||
(uint) wsrep_binlog_format(),
|
(uint) wsrep_binlog_format(),
|
||||||
binlog_filter->db_ok(db.str)));
|
binlog_filter->db_ok(db.str)));
|
||||||
#endif
|
if (WSREP_NNULL(this) && is_current_stmt_binlog_format_row())
|
||||||
|
binlog_prepare_for_row_logging();
|
||||||
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int THD::decide_logging_format_low(TABLE *table)
|
int THD::decide_logging_format_low(TABLE *table)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("decide_logging_format_low");
|
||||||
/*
|
/*
|
||||||
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
|
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
|
||||||
can be unsafe.
|
can be unsafe.
|
||||||
*/
|
*/
|
||||||
if(wsrep_binlog_format() <= BINLOG_FORMAT_STMT &&
|
if (wsrep_binlog_format() <= BINLOG_FORMAT_STMT &&
|
||||||
!is_current_stmt_binlog_format_row() &&
|
!is_current_stmt_binlog_format_row() &&
|
||||||
!lex->is_stmt_unsafe() &&
|
!lex->is_stmt_unsafe() &&
|
||||||
lex->sql_command == SQLCOM_INSERT &&
|
lex->duplicates == DUP_UPDATE)
|
||||||
lex->duplicates == DUP_UPDATE)
|
|
||||||
{
|
{
|
||||||
uint unique_keys= 0;
|
uint unique_keys= 0;
|
||||||
uint keys= table->s->keys, i= 0;
|
uint keys= table->s->keys, i= 0;
|
||||||
@@ -6376,27 +6381,22 @@ exit:;
|
|||||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
|
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
|
||||||
binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags();
|
binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags();
|
||||||
set_current_stmt_binlog_format_row_if_mixed();
|
set_current_stmt_binlog_format_row_if_mixed();
|
||||||
return 1;
|
if (is_current_stmt_binlog_format_row())
|
||||||
|
binlog_prepare_for_row_logging();
|
||||||
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Implementation of interface to write rows to the binary log through the
|
|
||||||
thread. The thread is responsible for writing the rows it has
|
|
||||||
inserted/updated/deleted.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MYSQL_CLIENT
|
#ifndef MYSQL_CLIENT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Template member function for ensuring that there is an rows log
|
Template member function for ensuring that there is an rows log
|
||||||
event of the apropriate type before proceeding.
|
event of the apropriate type before proceeding.
|
||||||
|
|
||||||
PRE CONDITION:
|
PRE CONDITION:
|
||||||
- Events of type 'RowEventT' have the type code 'type_code'.
|
- Events of type 'RowEventT' have the type code 'type_code'.
|
||||||
|
|
||||||
POST CONDITION:
|
POST CONDITION:
|
||||||
If a non-NULL pointer is returned, the pending event for thread 'thd' will
|
If a non-NULL pointer is returned, the pending event for thread 'thd' will
|
||||||
be an event of type 'RowEventT' (which have the type code 'type_code')
|
be an event of type 'RowEventT' (which have the type code 'type_code')
|
||||||
@@ -6814,7 +6814,8 @@ void THD::binlog_prepare_row_images(TABLE *table)
|
|||||||
*/
|
*/
|
||||||
if (table->s->primary_key < MAX_KEY &&
|
if (table->s->primary_key < MAX_KEY &&
|
||||||
(thd->variables.binlog_row_image < BINLOG_ROW_IMAGE_FULL) &&
|
(thd->variables.binlog_row_image < BINLOG_ROW_IMAGE_FULL) &&
|
||||||
!ha_check_storage_engine_flag(table->s->db_type(), HTON_NO_BINLOG_ROW_OPT))
|
!ha_check_storage_engine_flag(table->s->db_type(),
|
||||||
|
HTON_NO_BINLOG_ROW_OPT))
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
Just to be sure that tmp_set is currently not in use as
|
Just to be sure that tmp_set is currently not in use as
|
||||||
@@ -6859,7 +6860,7 @@ void THD::binlog_prepare_row_images(TABLE *table)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int THD::binlog_remove_pending_rows_event(bool clear_maps,
|
int THD::binlog_remove_pending_rows_event(bool reset_stmt,
|
||||||
bool is_transactional)
|
bool is_transactional)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("THD::binlog_remove_pending_rows_event");
|
DBUG_ENTER("THD::binlog_remove_pending_rows_event");
|
||||||
@@ -6873,12 +6874,12 @@ int THD::binlog_remove_pending_rows_event(bool clear_maps,
|
|||||||
|
|
||||||
mysql_bin_log.remove_pending_rows_event(this, is_transactional);
|
mysql_bin_log.remove_pending_rows_event(this, is_transactional);
|
||||||
|
|
||||||
if (clear_maps)
|
if (reset_stmt)
|
||||||
binlog_table_maps= 0;
|
reset_binlog_for_next_statement();
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int THD::binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional)
|
int THD::binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("THD::binlog_flush_pending_rows_event");
|
DBUG_ENTER("THD::binlog_flush_pending_rows_event");
|
||||||
@@ -6904,9 +6905,8 @@ int THD::binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional)
|
|||||||
if (stmt_end)
|
if (stmt_end)
|
||||||
{
|
{
|
||||||
pending->set_flags(Rows_log_event::STMT_END_F);
|
pending->set_flags(Rows_log_event::STMT_END_F);
|
||||||
binlog_table_maps= 0;
|
reset_binlog_for_next_statement();
|
||||||
}
|
}
|
||||||
|
|
||||||
error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0,
|
error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0,
|
||||||
is_transactional);
|
is_transactional);
|
||||||
}
|
}
|
||||||
@@ -7278,8 +7278,11 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
|
|||||||
suppress_use, errcode);
|
suppress_use, errcode);
|
||||||
error= mysql_bin_log.write(&qinfo);
|
error= mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
row logged binlog may not have been reset in the case of locked tables
|
||||||
|
*/
|
||||||
|
reset_binlog_for_next_statement();
|
||||||
|
|
||||||
binlog_table_maps= 0;
|
|
||||||
DBUG_RETURN(error >= 0 ? error : 1);
|
DBUG_RETURN(error >= 0 ? error : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -75,14 +75,15 @@ void set_thd_stage_info(void *thd,
|
|||||||
#include "wsrep_condition_variable.h"
|
#include "wsrep_condition_variable.h"
|
||||||
|
|
||||||
class Wsrep_applier_service;
|
class Wsrep_applier_service;
|
||||||
|
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
class Reprepare_observer;
|
class Reprepare_observer;
|
||||||
class Relay_log_info;
|
class Relay_log_info;
|
||||||
struct rpl_group_info;
|
struct rpl_group_info;
|
||||||
class Rpl_filter;
|
class Rpl_filter;
|
||||||
class Query_log_event;
|
class Query_log_event;
|
||||||
class Load_log_event;
|
class Load_log_event;
|
||||||
|
class Log_event_writer;
|
||||||
class sp_rcontext;
|
class sp_rcontext;
|
||||||
class sp_cache;
|
class sp_cache;
|
||||||
class Lex_input_stream;
|
class Lex_input_stream;
|
||||||
@@ -737,11 +738,6 @@ typedef struct system_variables
|
|||||||
my_bool query_cache_strip_comments;
|
my_bool query_cache_strip_comments;
|
||||||
my_bool sql_log_slow;
|
my_bool sql_log_slow;
|
||||||
my_bool sql_log_bin;
|
my_bool sql_log_bin;
|
||||||
/*
|
|
||||||
A flag to help detect whether binary logging was temporarily disabled
|
|
||||||
(see tmp_disable_binlog(A) macro).
|
|
||||||
*/
|
|
||||||
my_bool sql_log_bin_off;
|
|
||||||
my_bool binlog_annotate_row_events;
|
my_bool binlog_annotate_row_events;
|
||||||
my_bool binlog_direct_non_trans_update;
|
my_bool binlog_direct_non_trans_update;
|
||||||
my_bool column_compression_zlib_wrap;
|
my_bool column_compression_zlib_wrap;
|
||||||
@@ -2576,14 +2572,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
void binlog_start_trans_and_stmt();
|
void binlog_start_trans_and_stmt();
|
||||||
void binlog_set_stmt_begin();
|
void binlog_set_stmt_begin();
|
||||||
int binlog_write_table_map(TABLE *table, bool is_transactional,
|
|
||||||
bool *with_annotate= 0);
|
|
||||||
int binlog_write_row(TABLE* table, bool is_transactional,
|
int binlog_write_row(TABLE* table, bool is_transactional,
|
||||||
const uchar *buf);
|
const uchar *buf);
|
||||||
int binlog_delete_row(TABLE* table, bool is_transactional,
|
int binlog_delete_row(TABLE* table, bool is_transactional,
|
||||||
const uchar *buf);
|
const uchar *buf);
|
||||||
int binlog_update_row(TABLE* table, bool is_transactional,
|
int binlog_update_row(TABLE* table, bool is_transactional,
|
||||||
const uchar *old_data, const uchar *new_data);
|
const uchar *old_data, const uchar *new_data);
|
||||||
|
bool prepare_handlers_for_update(uint flag);
|
||||||
|
bool binlog_write_annotated_row(Log_event_writer *writer);
|
||||||
|
void binlog_prepare_for_row_logging();
|
||||||
|
bool binlog_write_table_maps();
|
||||||
|
bool binlog_write_table_map(TABLE *table, bool with_annotate);
|
||||||
static void binlog_prepare_row_images(TABLE* table);
|
static void binlog_prepare_row_images(TABLE* table);
|
||||||
|
|
||||||
void set_server_id(uint32 sid) { variables.server_id = sid; }
|
void set_server_id(uint32 sid) { variables.server_id = sid; }
|
||||||
@@ -2677,22 +2676,20 @@ private:
|
|||||||
*/
|
*/
|
||||||
enum_binlog_format current_stmt_binlog_format;
|
enum_binlog_format current_stmt_binlog_format;
|
||||||
|
|
||||||
/*
|
|
||||||
Number of outstanding table maps, i.e., table maps in the
|
|
||||||
transaction cache.
|
|
||||||
*/
|
|
||||||
uint binlog_table_maps;
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/* 1 if binlog table maps has been written */
|
||||||
|
bool binlog_table_maps;
|
||||||
|
|
||||||
void issue_unsafe_warnings();
|
void issue_unsafe_warnings();
|
||||||
void reset_unsafe_warnings()
|
void reset_unsafe_warnings()
|
||||||
{ binlog_unsafe_warning_flags= 0; }
|
{ binlog_unsafe_warning_flags= 0; }
|
||||||
|
|
||||||
uint get_binlog_table_maps() const {
|
void reset_binlog_for_next_statement()
|
||||||
return binlog_table_maps;
|
{
|
||||||
}
|
|
||||||
void clear_binlog_table_maps() {
|
|
||||||
binlog_table_maps= 0;
|
binlog_table_maps= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* MYSQL_CLIENT */
|
#endif /* MYSQL_CLIENT */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -5170,11 +5167,10 @@ my_eof(THD *thd)
|
|||||||
#define tmp_disable_binlog(A) \
|
#define tmp_disable_binlog(A) \
|
||||||
{ulonglong tmp_disable_binlog__save_options= (A)->variables.option_bits; \
|
{ulonglong tmp_disable_binlog__save_options= (A)->variables.option_bits; \
|
||||||
(A)->variables.option_bits&= ~OPTION_BIN_LOG; \
|
(A)->variables.option_bits&= ~OPTION_BIN_LOG; \
|
||||||
(A)->variables.sql_log_bin_off= 1;
|
(A)->variables.option_bits|= OPTION_BIN_TMP_LOG_OFF;
|
||||||
|
|
||||||
#define reenable_binlog(A) \
|
#define reenable_binlog(A) \
|
||||||
(A)->variables.option_bits= tmp_disable_binlog__save_options; \
|
(A)->variables.option_bits= tmp_disable_binlog__save_options; }
|
||||||
(A)->variables.sql_log_bin_off= 0;}
|
|
||||||
|
|
||||||
|
|
||||||
inline date_conv_mode_t sql_mode_for_dates(THD *thd)
|
inline date_conv_mode_t sql_mode_for_dates(THD *thd)
|
||||||
|
@@ -959,6 +959,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
goto values_loop_end;
|
goto values_loop_end;
|
||||||
|
|
||||||
THD_STAGE_INFO(thd, stage_update);
|
THD_STAGE_INFO(thd, stage_update);
|
||||||
|
thd->decide_logging_format_low(table);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("iteration %llu", iteration));
|
DBUG_PRINT("info", ("iteration %llu", iteration));
|
||||||
@@ -1071,7 +1072,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
thd->decide_logging_format_low(table);
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
if (lock_type == TL_WRITE_DELAYED)
|
if (lock_type == TL_WRITE_DELAYED)
|
||||||
{
|
{
|
||||||
@@ -3051,6 +3051,8 @@ bool Delayed_insert::open_and_lock_table()
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
table->copy_blobs= 1;
|
table->copy_blobs= 1;
|
||||||
|
|
||||||
|
table->file->prepare_for_row_logging();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3110,6 +3112,8 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
|||||||
at which rows are inserted cannot be determined in mixed mode.
|
at which rows are inserted cannot be determined in mixed mode.
|
||||||
*/
|
*/
|
||||||
thd->set_current_stmt_binlog_format_row_if_mixed();
|
thd->set_current_stmt_binlog_format_row_if_mixed();
|
||||||
|
/* Don't annotate insert delayed binlog events */
|
||||||
|
thd->variables.binlog_annotate_row_events= 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Clone tickets representing protection against GRL and the lock on
|
Clone tickets representing protection against GRL and the lock on
|
||||||
@@ -3314,8 +3318,19 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
|||||||
di->table->file->delete_update_handler();
|
di->table->file->delete_update_handler();
|
||||||
di->group_count=0;
|
di->group_count=0;
|
||||||
mysql_audit_release(thd);
|
mysql_audit_release(thd);
|
||||||
|
/*
|
||||||
|
Reset binlog. We can't call ha_reset() for the table as this will
|
||||||
|
reset the table maps we have calculated earlier.
|
||||||
|
*/
|
||||||
mysql_mutex_lock(&di->mutex);
|
mysql_mutex_lock(&di->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reset binlog. We can't call ha_reset() for the table as this will
|
||||||
|
reset the table maps we have calculated earlier.
|
||||||
|
*/
|
||||||
|
thd->reset_binlog_for_next_statement();
|
||||||
|
|
||||||
if (di->tables_in_use)
|
if (di->tables_in_use)
|
||||||
mysql_cond_broadcast(&di->cond_client); // If waiting clients
|
mysql_cond_broadcast(&di->cond_client); // If waiting clients
|
||||||
}
|
}
|
||||||
@@ -3407,9 +3422,7 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
ulong max_rows;
|
ulong max_rows;
|
||||||
bool has_trans = TRUE;
|
bool using_ignore= 0, using_opt_replace= 0, using_bin_log;
|
||||||
bool using_ignore= 0, using_opt_replace= 0,
|
|
||||||
using_bin_log= mysql_bin_log.is_open();
|
|
||||||
delayed_row *row;
|
delayed_row *row;
|
||||||
DBUG_ENTER("handle_inserts");
|
DBUG_ENTER("handle_inserts");
|
||||||
|
|
||||||
@@ -3443,7 +3456,13 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
|
|
||||||
if (table->file->ha_rnd_init_with_error(0))
|
if (table->file->ha_rnd_init_with_error(0))
|
||||||
goto err;
|
goto err;
|
||||||
|
/*
|
||||||
|
We have to call prepare_for_row_logging() as the second call to
|
||||||
|
handler_writes() will not have called decide_logging_format.
|
||||||
|
*/
|
||||||
|
table->file->prepare_for_row_logging();
|
||||||
table->file->prepare_for_insert();
|
table->file->prepare_for_insert();
|
||||||
|
using_bin_log= table->file->row_logging;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We can't use row caching when using the binary log because if
|
We can't use row caching when using the binary log because if
|
||||||
@@ -3452,6 +3471,7 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
*/
|
*/
|
||||||
if (!using_bin_log)
|
if (!using_bin_log)
|
||||||
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||||
|
|
||||||
mysql_mutex_lock(&mutex);
|
mysql_mutex_lock(&mutex);
|
||||||
|
|
||||||
while ((row=rows.get()))
|
while ((row=rows.get()))
|
||||||
@@ -3480,8 +3500,8 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
Guaranteed that the INSERT DELAYED STMT will not be here
|
Guaranteed that the INSERT DELAYED STMT will not be here
|
||||||
in SBR when mysql binlog is enabled.
|
in SBR when mysql binlog is enabled.
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(!(mysql_bin_log.is_open() &&
|
DBUG_ASSERT(!mysql_bin_log.is_open() ||
|
||||||
!thd.is_current_stmt_binlog_format_row()));
|
thd.is_current_stmt_binlog_format_row());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is the first value of an INSERT statement.
|
This is the first value of an INSERT statement.
|
||||||
@@ -3639,10 +3659,9 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
|
|
||||||
TODO: Move the logging to last in the sequence of rows.
|
TODO: Move the logging to last in the sequence of rows.
|
||||||
*/
|
*/
|
||||||
has_trans= thd.lex->sql_command == SQLCOM_CREATE_TABLE ||
|
if (table->file->row_logging &&
|
||||||
table->file->has_transactions();
|
thd.binlog_flush_pending_rows_event(TRUE,
|
||||||
if (thd.is_current_stmt_binlog_format_row() &&
|
table->file->row_logging_has_trans))
|
||||||
thd.binlog_flush_pending_rows_event(TRUE, has_trans))
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (unlikely((error=table->file->extra(HA_EXTRA_NO_CACHE))))
|
if (unlikely((error=table->file->extra(HA_EXTRA_NO_CACHE))))
|
||||||
@@ -4548,6 +4567,18 @@ TABLE *select_create::create_table_from_items(THD *thd, List<Item> *items,
|
|||||||
/* purecov: end */
|
/* purecov: end */
|
||||||
}
|
}
|
||||||
table->s->table_creation_was_logged= save_table_creation_was_logged;
|
table->s->table_creation_was_logged= save_table_creation_was_logged;
|
||||||
|
if (!table->s->tmp_table)
|
||||||
|
table->file->prepare_for_row_logging();
|
||||||
|
|
||||||
|
/*
|
||||||
|
If slave is converting a statement event to row events, log the original
|
||||||
|
create statement as an annotated row
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_REPLICATION
|
||||||
|
if (thd->slave_thread && opt_replicate_annotate_row_events &&
|
||||||
|
thd->is_current_stmt_binlog_format_row())
|
||||||
|
thd->variables.binlog_annotate_row_events= 1;
|
||||||
|
#endif
|
||||||
DBUG_RETURN(table);
|
DBUG_RETURN(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4792,6 +4823,7 @@ bool binlog_create_table(THD *thd, TABLE *table)
|
|||||||
logged
|
logged
|
||||||
*/
|
*/
|
||||||
thd->set_current_stmt_binlog_format_row();
|
thd->set_current_stmt_binlog_format_row();
|
||||||
|
table->file->prepare_for_row_logging();
|
||||||
return binlog_show_create_table(thd, table, 0) != 0;
|
return binlog_show_create_table(thd, table, 0) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4854,6 +4886,9 @@ bool select_create::send_eof()
|
|||||||
if (table->s->tmp_table)
|
if (table->s->tmp_table)
|
||||||
thd->transaction.stmt.mark_created_temp_table();
|
thd->transaction.stmt.mark_created_temp_table();
|
||||||
|
|
||||||
|
if (thd->slave_thread)
|
||||||
|
thd->variables.binlog_annotate_row_events= 0;
|
||||||
|
|
||||||
if (prepare_eof())
|
if (prepare_eof())
|
||||||
{
|
{
|
||||||
abort_result_set();
|
abort_result_set();
|
||||||
|
@@ -7436,6 +7436,12 @@ void THD::reset_for_next_command(bool do_clear_error)
|
|||||||
DBUG_ENTER("THD::reset_for_next_command");
|
DBUG_ENTER("THD::reset_for_next_command");
|
||||||
DBUG_ASSERT(!spcont); /* not for substatements of routines */
|
DBUG_ASSERT(!spcont); /* not for substatements of routines */
|
||||||
DBUG_ASSERT(!in_sub_stmt);
|
DBUG_ASSERT(!in_sub_stmt);
|
||||||
|
/*
|
||||||
|
Table maps should have been reset after previous statement except in the
|
||||||
|
case where we have locked tables
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(binlog_table_maps == 0 ||
|
||||||
|
locked_tables_mode == LTM_LOCK_TABLES);
|
||||||
|
|
||||||
if (likely(do_clear_error))
|
if (likely(do_clear_error))
|
||||||
{
|
{
|
||||||
|
@@ -2168,14 +2168,13 @@ static bool finalize_install(THD *thd, TABLE *table, const LEX_CSTRING *name,
|
|||||||
of the insert into the plugin table, so that it is not replicated in
|
of the insert into the plugin table, so that it is not replicated in
|
||||||
row based mode.
|
row based mode.
|
||||||
*/
|
*/
|
||||||
tmp_disable_binlog(thd);
|
DBUG_ASSERT(!table->file->row_logging);
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
restore_record(table, s->default_values);
|
restore_record(table, s->default_values);
|
||||||
table->field[0]->store(name->str, name->length, system_charset_info);
|
table->field[0]->store(name->str, name->length, system_charset_info);
|
||||||
table->field[1]->store(tmp->plugin_dl->dl.str, tmp->plugin_dl->dl.length,
|
table->field[1]->store(tmp->plugin_dl->dl.str, tmp->plugin_dl->dl.length,
|
||||||
files_charset_info);
|
files_charset_info);
|
||||||
error= table->file->ha_write_row(table->record[0]);
|
error= table->file->ha_write_row(table->record[0]);
|
||||||
reenable_binlog(thd);
|
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
{
|
{
|
||||||
table->file->print_error(error, MYF(0));
|
table->file->print_error(error, MYF(0));
|
||||||
@@ -2322,9 +2321,8 @@ static bool do_uninstall(THD *thd, TABLE *table, const LEX_CSTRING *name)
|
|||||||
of the delete from the plugin table, so that it is not replicated in
|
of the delete from the plugin table, so that it is not replicated in
|
||||||
row based mode.
|
row based mode.
|
||||||
*/
|
*/
|
||||||
tmp_disable_binlog(thd);
|
table->file->row_logging= 0; // No logging
|
||||||
error= table->file->ha_delete_row(table->record[0]);
|
error= table->file->ha_delete_row(table->record[0]);
|
||||||
reenable_binlog(thd);
|
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
{
|
{
|
||||||
table->file->print_error(error, MYF(0));
|
table->file->print_error(error, MYF(0));
|
||||||
|
@@ -180,6 +180,8 @@
|
|||||||
#define OPTION_NO_QUERY_CACHE (1ULL << 39) // SELECT, user
|
#define OPTION_NO_QUERY_CACHE (1ULL << 39) // SELECT, user
|
||||||
#define OPTION_PROCEDURE_CLAUSE (1ULL << 40) // Internal usage
|
#define OPTION_PROCEDURE_CLAUSE (1ULL << 40) // Internal usage
|
||||||
#define SELECT_NO_UNLOCK (1ULL << 41) // SELECT, intern
|
#define SELECT_NO_UNLOCK (1ULL << 41) // SELECT, intern
|
||||||
|
#define SELECT_NO_UNLOCK (1ULL << 41) // SELECT, intern
|
||||||
|
#define OPTION_BIN_TMP_LOG_OFF (1ULL << 42) // disable binlog, intern
|
||||||
|
|
||||||
#define OPTION_LEX_FOUND_COMMENT (1ULL << 0) // intern, parser
|
#define OPTION_LEX_FOUND_COMMENT (1ULL << 0) // intern, parser
|
||||||
|
|
||||||
|
@@ -580,7 +580,6 @@ void sequence_definition::adjust_values(longlong next_value)
|
|||||||
int sequence_definition::write_initial_sequence(TABLE *table)
|
int sequence_definition::write_initial_sequence(TABLE *table)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
THD *thd= table->in_use;
|
|
||||||
MY_BITMAP *save_write_set;
|
MY_BITMAP *save_write_set;
|
||||||
|
|
||||||
store_fields(table);
|
store_fields(table);
|
||||||
@@ -588,15 +587,14 @@ int sequence_definition::write_initial_sequence(TABLE *table)
|
|||||||
table->s->sequence->copy(this);
|
table->s->sequence->copy(this);
|
||||||
/*
|
/*
|
||||||
Sequence values will be replicated as a statement
|
Sequence values will be replicated as a statement
|
||||||
like 'create sequence'. So disable binary log temporarily
|
like 'create sequence'. So disable row logging for this table & statement
|
||||||
*/
|
*/
|
||||||
tmp_disable_binlog(thd);
|
table->file->row_logging= table->file->row_logging_init= 0;
|
||||||
save_write_set= table->write_set;
|
save_write_set= table->write_set;
|
||||||
table->write_set= &table->s->all_set;
|
table->write_set= &table->s->all_set;
|
||||||
table->s->sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
|
table->s->sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
|
||||||
error= table->file->ha_write_row(table->record[0]);
|
error= table->file->ha_write_row(table->record[0]);
|
||||||
table->s->sequence->initialized= SEQUENCE::SEQ_UNINTIALIZED;
|
table->s->sequence->initialized= SEQUENCE::SEQ_UNINTIALIZED;
|
||||||
reenable_binlog(thd);
|
|
||||||
table->write_set= save_write_set;
|
table->write_set= save_write_set;
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
table->file->print_error(error, MYF(0));
|
table->file->print_error(error, MYF(0));
|
||||||
|
@@ -404,6 +404,7 @@ insert_server(THD *thd, FOREIGN_SERVER *server)
|
|||||||
/* need to open before acquiring THR_LOCK_plugin or it will deadlock */
|
/* need to open before acquiring THR_LOCK_plugin or it will deadlock */
|
||||||
if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
|
if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
|
||||||
goto end;
|
goto end;
|
||||||
|
table->file->row_logging= 0; // Don't log to binary log
|
||||||
|
|
||||||
/* insert the server into the table */
|
/* insert the server into the table */
|
||||||
if (unlikely(error= insert_server_record(table, server)))
|
if (unlikely(error= insert_server_record(table, server)))
|
||||||
@@ -542,9 +543,9 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
DBUG_ENTER("insert_server_record");
|
DBUG_ENTER("insert_server_record");
|
||||||
tmp_disable_binlog(table->in_use);
|
DBUG_ASSERT(!table->file->row_logging);
|
||||||
table->use_all_columns();
|
|
||||||
|
|
||||||
|
table->use_all_columns();
|
||||||
empty_record(table);
|
empty_record(table);
|
||||||
|
|
||||||
/* set the field that's the PK to the value we're looking for */
|
/* set the field that's the PK to the value we're looking for */
|
||||||
@@ -577,8 +578,6 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
error= ER_FOREIGN_SERVER_EXISTS;
|
error= ER_FOREIGN_SERVER_EXISTS;
|
||||||
|
|
||||||
reenable_binlog(table->in_use);
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -895,7 +894,8 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
{
|
{
|
||||||
int error=0;
|
int error=0;
|
||||||
DBUG_ENTER("update_server_record");
|
DBUG_ENTER("update_server_record");
|
||||||
tmp_disable_binlog(table->in_use);
|
DBUG_ASSERT(!table->file->row_logging);
|
||||||
|
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
/* set the field that's the PK to the value we're looking for */
|
/* set the field that's the PK to the value we're looking for */
|
||||||
table->field[0]->store(server->server_name,
|
table->field[0]->store(server->server_name,
|
||||||
@@ -931,7 +931,6 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
reenable_binlog(table->in_use);
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -956,7 +955,8 @@ delete_server_record(TABLE *table, LEX_CSTRING *name)
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
DBUG_ENTER("delete_server_record");
|
DBUG_ENTER("delete_server_record");
|
||||||
tmp_disable_binlog(table->in_use);
|
DBUG_ASSERT(!table->file->row_logging);
|
||||||
|
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
|
|
||||||
/* set the field that's the PK to the value we're looking for */
|
/* set the field that's the PK to the value we're looking for */
|
||||||
@@ -980,7 +980,6 @@ delete_server_record(TABLE *table, LEX_CSTRING *name)
|
|||||||
table->file->print_error(error, MYF(0));
|
table->file->print_error(error, MYF(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
reenable_binlog(table->in_use);
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10471,6 +10471,7 @@ do_continue:;
|
|||||||
No additional logging of query is needed
|
No additional logging of query is needed
|
||||||
*/
|
*/
|
||||||
binlog_done= 1;
|
binlog_done= 1;
|
||||||
|
DBUG_ASSERT(new_table->file->row_logging);
|
||||||
new_table->mark_columns_needed_for_insert();
|
new_table->mark_columns_needed_for_insert();
|
||||||
thd->binlog_write_table_map(new_table, 1);
|
thd->binlog_write_table_map(new_table, 1);
|
||||||
}
|
}
|
||||||
|
@@ -1330,7 +1330,8 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
|
bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
|
||||||
const LEX_CSTRING *table_name, TABLE *table,
|
const LEX_CSTRING *table_name,
|
||||||
|
TABLE *table,
|
||||||
bool names_only)
|
bool names_only)
|
||||||
{
|
{
|
||||||
char path_buff[FN_REFLEN];
|
char path_buff[FN_REFLEN];
|
||||||
|
@@ -5269,7 +5269,6 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
|
|||||||
/* used in RBR Triggers */
|
/* used in RBR Triggers */
|
||||||
master_had_triggers= 0;
|
master_had_triggers= 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Catch wrong handling of the auto_increment_field_not_null. */
|
/* Catch wrong handling of the auto_increment_field_not_null. */
|
||||||
DBUG_ASSERT(!auto_increment_field_not_null);
|
DBUG_ASSERT(!auto_increment_field_not_null);
|
||||||
auto_increment_field_not_null= FALSE;
|
auto_increment_field_not_null= FALSE;
|
||||||
@@ -5284,7 +5283,6 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
notnull_cond= 0;
|
notnull_cond= 0;
|
||||||
|
|
||||||
DBUG_ASSERT(!file->keyread_enabled());
|
DBUG_ASSERT(!file->keyread_enabled());
|
||||||
|
|
||||||
restore_record(this, s->default_values);
|
restore_record(this, s->default_values);
|
||||||
@@ -7293,8 +7291,7 @@ void TABLE::mark_columns_per_binlog_row_image()
|
|||||||
If in RBR we may need to mark some extra columns,
|
If in RBR we may need to mark some extra columns,
|
||||||
depending on the binlog-row-image command line argument.
|
depending on the binlog-row-image command line argument.
|
||||||
*/
|
*/
|
||||||
if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) &&
|
if (file->row_logging &&
|
||||||
thd->is_current_stmt_binlog_format_row() &&
|
|
||||||
!ha_check_storage_engine_flag(s->db_type(), HTON_NO_BINLOG_ROW_OPT))
|
!ha_check_storage_engine_flag(s->db_type(), HTON_NO_BINLOG_ROW_OPT))
|
||||||
{
|
{
|
||||||
/* if there is no PK, then mark all columns for the BI. */
|
/* if there is no PK, then mark all columns for the BI. */
|
||||||
|
@@ -1124,13 +1124,11 @@ TABLE *THD::open_temporary_table(TMP_TABLE_SHARE *share,
|
|||||||
|
|
||||||
table->reginfo.lock_type= TL_WRITE; /* Simulate locked */
|
table->reginfo.lock_type= TL_WRITE; /* Simulate locked */
|
||||||
table->grant.privilege= TMP_TABLE_ACLS;
|
table->grant.privilege= TMP_TABLE_ACLS;
|
||||||
|
table->query_id= query_id;
|
||||||
share->tmp_table= (table->file->has_transaction_manager() ?
|
share->tmp_table= (table->file->has_transaction_manager() ?
|
||||||
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
|
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
|
||||||
share->not_usable_by_query_cache= 1;
|
share->not_usable_by_query_cache= 1;
|
||||||
|
|
||||||
table->pos_in_table_list= 0;
|
|
||||||
table->query_id= query_id;
|
|
||||||
|
|
||||||
/* Add table to the head of table list. */
|
/* Add table to the head of table list. */
|
||||||
share->all_tmp_tables.push_front(table);
|
share->all_tmp_tables.push_front(table);
|
||||||
|
|
||||||
|
@@ -302,8 +302,10 @@ bool trans_commit_implicit(THD *thd)
|
|||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (thd->variables.option_bits & OPTION_GTID_BEGIN)
|
if (thd->variables.option_bits & OPTION_GTID_BEGIN)
|
||||||
|
{
|
||||||
DBUG_PRINT("error", ("OPTION_GTID_BEGIN is set. "
|
DBUG_PRINT("error", ("OPTION_GTID_BEGIN is set. "
|
||||||
"Master and slave will have different GTID values"));
|
"Master and slave will have different GTID values"));
|
||||||
|
}
|
||||||
|
|
||||||
if (thd->in_multi_stmt_transaction_mode() ||
|
if (thd->in_multi_stmt_transaction_mode() ||
|
||||||
(thd->variables.option_bits & OPTION_TABLE_LOCK))
|
(thd->variables.option_bits & OPTION_TABLE_LOCK))
|
||||||
@@ -361,9 +363,9 @@ bool trans_rollback(THD *thd)
|
|||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
repl_semisync_master.wait_after_rollback(thd, FALSE);
|
repl_semisync_master.wait_after_rollback(thd, FALSE);
|
||||||
#endif
|
#endif
|
||||||
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
|
|
||||||
/* Reset the binlog transaction marker */
|
/* Reset the binlog transaction marker */
|
||||||
thd->variables.option_bits&= ~OPTION_GTID_BEGIN;
|
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG |
|
||||||
|
OPTION_GTID_BEGIN);
|
||||||
thd->transaction.all.reset();
|
thd->transaction.all.reset();
|
||||||
thd->lex->start_transaction_opt= 0;
|
thd->lex->start_transaction_opt= 0;
|
||||||
|
|
||||||
|
@@ -222,7 +222,7 @@ extern wsrep_seqno_t wsrep_locked_seqno;
|
|||||||
/* use xxxxxx_NNULL macros when thd pointer is guaranteed to be non-null to
|
/* use xxxxxx_NNULL macros when thd pointer is guaranteed to be non-null to
|
||||||
* avoid compiler warnings (GCC 6 and later) */
|
* avoid compiler warnings (GCC 6 and later) */
|
||||||
#define WSREP_NNULL(thd) \
|
#define WSREP_NNULL(thd) \
|
||||||
(WSREP_ON && thd->variables.wsrep_on)
|
(thd->variables.wsrep_on && WSREP_ON)
|
||||||
|
|
||||||
#define WSREP(thd) \
|
#define WSREP(thd) \
|
||||||
(thd && WSREP_NNULL(thd))
|
(thd && WSREP_NNULL(thd))
|
||||||
|
Reference in New Issue
Block a user