From 91be2212c69d727d0b104f70cb32c4639397338c Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Sat, 15 Jun 2019 19:55:57 +0300 Subject: MDEV-17045: MyRocks tables cannot be updated when binlog_format=MIXED. --- storage/rocksdb/ha_rocksdb.cc | 53 ++++++++++++++++------ storage/rocksdb/ha_rocksdb.h | 26 +---------- .../rocksdb/r/mariadb_misc_binlog.result | 11 ++++- .../mysql-test/rocksdb/r/rpl_statement.result | 4 +- .../mysql-test/rocksdb/t/mariadb_misc_binlog.test | 12 ++++- .../mysql-test/rocksdb/t/rpl_statement.test | 4 +- 6 files changed, 65 insertions(+), 45 deletions(-) (limited to 'storage') diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 3331b94c62c..cb289fb0077 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -11025,6 +11025,41 @@ void ha_rocksdb::read_thd_vars(THD *const thd) { m_checksums_pct = THDVAR(thd, checksums_pct); } +ulonglong ha_rocksdb::table_flags() const +{ + DBUG_ENTER_FUNC(); + + /* + HA_BINLOG_STMT_CAPABLE + Upstream: MyRocks advertises itself as it supports SBR, but has additional + checks in ha_rocksdb::external_lock()/ start_stmt() which will return an + error if one tries to run the statement. + Exceptions: @@rocksdb_unsafe_for_binlog or we are an SQL slave thread. + + MariaDB: Inform the upper layer we don't support SBR, so it switches to RBR + if possible. The exceptions are the same as with the upstream. + + HA_REC_NOT_IN_SEQ + If we don't set it, filesort crashes, because it assumes rowids are + 1..8 byte numbers + HA_PRIMARY_KEY_IN_READ_INDEX + This flag is always set, even for tables that: + - have no PK + - have some (or all) of PK that can't be decoded from the secondary + index. + */ + THD *thd= ha_thd(); + DBUG_RETURN(HA_BINLOG_ROW_CAPABLE | + ((thd && (THDVAR(thd, unsafe_for_binlog) ||thd->rgi_slave))? + HA_BINLOG_STMT_CAPABLE : 0) | + HA_REC_NOT_IN_SEQ | HA_CAN_INDEX_BLOBS | + HA_PRIMARY_KEY_IN_READ_INDEX | + HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_NULL_IN_KEY | + HA_PARTIAL_COLUMN_READ | + HA_TABLE_SCAN_ON_INDEX); +} + + /** @return @@ -11037,6 +11072,9 @@ int ha_rocksdb::external_lock(THD *const thd, int lock_type) { DBUG_ASSERT(thd != nullptr); int res = HA_EXIT_SUCCESS; +#if 0 + // MariaDB uses a different way to implement this, see ha_rocksdb::table_flags + int binlog_format = my_core::thd_binlog_format(thd); bool unsafe_for_binlog = THDVAR(ha_thd(), unsafe_for_binlog); @@ -11065,6 +11103,7 @@ int ha_rocksdb::external_lock(THD *const thd, int lock_type) { my_error(ER_REQUIRE_ROW_BINLOG_FORMAT, MYF(0)); DBUG_RETURN(HA_ERR_UNSUPPORTED); } +#endif if (lock_type == F_UNLCK) { Rdb_transaction *const tx = get_tx_from_thd(thd); @@ -11167,20 +11206,6 @@ int ha_rocksdb::external_lock(THD *const thd, int lock_type) { int ha_rocksdb::start_stmt(THD *const thd, thr_lock_type lock_type) { DBUG_ENTER_FUNC(); - /* - MariaDB: the following is a copy of the check in ha_rocksdb::external_lock: - */ - int binlog_format = my_core::thd_binlog_format(thd); - bool unsafe_for_binlog = THDVAR(ha_thd(), unsafe_for_binlog); - if (lock_type >= TL_WRITE_ALLOW_WRITE && - !thd->rgi_slave && !unsafe_for_binlog && - binlog_format != BINLOG_FORMAT_ROW && - binlog_format != BINLOG_FORMAT_UNSPEC && - my_core::thd_binlog_filter_ok(thd)) { - my_error(ER_REQUIRE_ROW_BINLOG_FORMAT, MYF(0)); - DBUG_RETURN(HA_ERR_UNSUPPORTED); - } - DBUG_ASSERT(thd != nullptr); Rdb_transaction *const tx = get_or_create_tx(thd); diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h index aae823fe4e1..a48d745fcf2 100644 --- a/storage/rocksdb/ha_rocksdb.h +++ b/storage/rocksdb/ha_rocksdb.h @@ -863,31 +863,7 @@ public: This is a list of flags that indicate what functionality the storage engine implements. The current table flags are documented in handler.h */ - ulonglong table_flags() const override { - DBUG_ENTER_FUNC(); - - /* - HA_BINLOG_STMT_CAPABLE - We are saying that this engine is just statement capable to have - an engine that can only handle statement-based logging. This is - used in testing. - HA_REC_NOT_IN_SEQ - If we don't set it, filesort crashes, because it assumes rowids are - 1..8 byte numbers - HA_PRIMARY_KEY_IN_READ_INDEX - This flag is always set, even for tables that: - - have no PK - - have some (or all) of PK that can't be decoded from the secondary - index. - */ - DBUG_RETURN(HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | - HA_REC_NOT_IN_SEQ | HA_CAN_INDEX_BLOBS | - HA_PRIMARY_KEY_IN_READ_INDEX | - HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_NULL_IN_KEY | - HA_PARTIAL_COLUMN_READ | - HA_TABLE_SCAN_ON_INDEX); - } - + ulonglong table_flags() const override ; private: bool init_with_fields(); /* no 'override' in MariaDB */ public: diff --git a/storage/rocksdb/mysql-test/rocksdb/r/mariadb_misc_binlog.result b/storage/rocksdb/mysql-test/rocksdb/r/mariadb_misc_binlog.result index e4ac62aa481..c37ab9461af 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/mariadb_misc_binlog.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/mariadb_misc_binlog.result @@ -18,7 +18,16 @@ set @tmp_bf= @@binlog_format; set binlog_format='STATEMENT'; lock tables t1 write; insert into t1 values(1); -ERROR HY000: Can't execute updates on master with binlog_format != ROW. +ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. unlock tables; set @@binlog_format=@tmp_bf; drop table t1; +# +# MDEV-17045: MyRocks tables cannot be updated when binlog_format=MIXED. +# +set @tmp_bf= @@binlog_format; +set binlog_format='MIXED'; +create table t1 (pk int primary key) engine=rocksdb; +insert into t1 values (1); +drop table t1; +set @@binlog_format=@tmp_bf; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rpl_statement.result b/storage/rocksdb/mysql-test/rocksdb/r/rpl_statement.result index cdf0c37e339..df1a60519db 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/rpl_statement.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/rpl_statement.result @@ -8,7 +8,7 @@ select @@binlog_format; STATEMENT create table t1 (pk int primary key) engine=rocksdb; insert into t1 values (1),(2),(3); -ERROR HY000: Can't execute updates on master with binlog_format != ROW. +ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. set session rocksdb_unsafe_for_binlog=on; insert into t1 values (1),(2),(3); select * from t1; @@ -19,7 +19,7 @@ pk delete from t1; set session rocksdb_unsafe_for_binlog=off; insert into t1 values (1),(2),(3); -ERROR HY000: Can't execute updates on master with binlog_format != ROW. +ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. set binlog_format=row; insert into t1 values (1),(2),(3); include/sync_slave_sql_with_master.inc diff --git a/storage/rocksdb/mysql-test/rocksdb/t/mariadb_misc_binlog.test b/storage/rocksdb/mysql-test/rocksdb/t/mariadb_misc_binlog.test index fb150f7a791..e32679e88a2 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/mariadb_misc_binlog.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/mariadb_misc_binlog.test @@ -21,10 +21,20 @@ unlock tables; set @tmp_bf= @@binlog_format; set binlog_format='STATEMENT'; lock tables t1 write; ---error ER_REQUIRE_ROW_BINLOG_FORMAT +--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE insert into t1 values(1); unlock tables; set @@binlog_format=@tmp_bf; drop table t1; +--echo # +--echo # MDEV-17045: MyRocks tables cannot be updated when binlog_format=MIXED. +--echo # +set @tmp_bf= @@binlog_format; +set binlog_format='MIXED'; +create table t1 (pk int primary key) engine=rocksdb; +insert into t1 values (1); +drop table t1; +set @@binlog_format=@tmp_bf; + diff --git a/storage/rocksdb/mysql-test/rocksdb/t/rpl_statement.test b/storage/rocksdb/mysql-test/rocksdb/t/rpl_statement.test index 29671308e9c..cb5f5e04b00 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/rpl_statement.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/rpl_statement.test @@ -12,7 +12,7 @@ connection master; select @@binlog_format; create table t1 (pk int primary key) engine=rocksdb; ---error ER_REQUIRE_ROW_BINLOG_FORMAT +--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE insert into t1 values (1),(2),(3); set session rocksdb_unsafe_for_binlog=on; @@ -21,7 +21,7 @@ select * from t1; delete from t1; set session rocksdb_unsafe_for_binlog=off; ---error ER_REQUIRE_ROW_BINLOG_FORMAT +--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE insert into t1 values (1),(2),(3); set binlog_format=row; -- cgit v1.2.1