[MDEV-17045] MyRocks tables cannot be updated when binlog_format=MIXED. Created: 2018-08-23  Updated: 2019-06-18  Resolved: 2019-06-16

Status: Closed
Project: MariaDB Server
Component/s: Storage Engine - RocksDB
Affects Version/s: 10.3
Fix Version/s: 10.2.25, 10.3.16, 10.4.6

Type: Bug Priority: Major
Reporter: Sergei Petrunia Assignee: Sergei Petrunia
Resolution: Fixed Votes: 0
Labels: None


 Description   

One cannot update a MyRocks table when they have binlog_format=MIXED:

MariaDB [test]> create table t1 (pk int primary key) engine=rocksdb;
Query OK, 0 rows affected (0.15 sec)
 
MariaDB [test]> insert into t1 values (1);
ERROR 4056 (HY000): Can't execute updates on master with binlog_format != ROW.
MariaDB [test]> 
MariaDB [test]> select @@binlog_format;
+-----------------+
| @@binlog_format |
+-----------------+
| MIXED           |
+-----------------+
1 row in set (0.00 sec)

This doesn't make sense from a user perspective:

  • MyRocks supports RBR only
  • binlog_format=MIXED means "try to use SBR but switch to RBR if required".
  • I expect that I'm able to run MyRocks with binlog_format=mixed and get RBR logging for updates to MyRocks tables.


 Comments   
Comment by Sergei Petrunia [ 2018-08-23 ]

Internally, it looks like this:

ha_rocksdb::table_flags() advertises that the storage engine supports both kinds of binlogging:

  ulonglong table_flags() const override {
    DBUG_ENTER_FUNC();
  ...
    DBUG_RETURN(HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
...

So if the SQL layer has logic to "use SBR if binlog_format=MIXED but storage engine doesn't support it", it will not be applied.

The statement proceeds to execute and hits this piece in ha_rocksdb::external_lock:

  if (lock_type == F_WRLCK && !thd->rgi_slave && !unsafe_for_binlog &&
      binlog_format != BINLOG_FORMAT_ROW &&
      binlog_format != BINLOG_FORMAT_UNSPEC &&
      thd->lex->sql_command != SQLCOM_LOCK_TABLES &&  // (*)
      thd->lex->sql_command != SQLCOM_ANALYZE &&   // (**)
      thd->lex->sql_command != SQLCOM_OPTIMIZE &&  // (**)
      thd->lex->sql_command != SQLCOM_FLUSH &&  // (**)
      my_core::thd_binlog_filter_ok(thd)) {
    my_error(ER_REQUIRE_ROW_BINLOG_FORMAT, MYF(0));
    DBUG_RETURN(HA_ERR_UNSUPPORTED);
  }

when invoked from here:

  #0  my_error (nr=4056, MyFlags=0) at /home/psergey/dev-git/10.3-r2/mysys/my_error.c:109
  #1  0x00007ffff4be06e8 in myrocks::ha_rocksdb::external_lock (this=0x7fff7001b6d0, thd=0x7fff700009a8, lock_type=1) at /home/psergey/dev-git/10.3-r2/storage/rocksdb/ha_rocksdb.cc:10681
  #2  0x0000555555cbdf6c in handler::ha_external_lock (this=0x7fff7001b6d0, thd=thd@entry=0x7fff700009a8, lock_type=lock_type@entry=1) at /home/psergey/dev-git/10.3-r2/sql/handler.cc:6121
  #3  0x0000555555d8238a in lock_external (count=1, tables=0x7fff70012028, thd=0x7fff700009a8) at /home/psergey/dev-git/10.3-r2/sql/lock.cc:396
  #4  mysql_lock_tables (thd=thd@entry=0x7fff700009a8, sql_lock=sql_lock@entry=0x7fff70011ff8, flags=<optimized out>, flags@entry=0) at /home/psergey/dev-git/10.3-r2/sql/lock.cc:342
  #5  0x0000555555d82cda in mysql_lock_tables (thd=thd@entry=0x7fff700009a8, tables=0x7fff70011ff0, count=<optimized out>, flags=0) at /home/psergey/dev-git/10.3-r2/sql/lock.cc:304
  #6  0x0000555555a90074 in lock_tables (thd=thd@entry=0x7fff700009a8, tables=0x7fff70011760, count=<optimized out>, flags=flags@entry=0) at /home/psergey/dev-git/10.3-r2/sql/sql_base.cc:5214
  #7  0x0000555555a91683 in open_and_lock_tables (thd=thd@entry=0x7fff700009a8, options=..., tables=tables@entry=0x7fff70011760, derived=derived@entry=true, flags=flags@entry=0, prelocking_strategy=prelocking_strategy@entry=0x7fffe4b60ca0) at /home/psergey/dev-git/10.3-r2/sql/sql_base.cc:4958

and this is why the statement fails with an error.

Comment by Sergei Petrunia [ 2018-08-23 ]

Possible solutions:

  • Don't advertise to SQL layer that MyROcks supports SBR (what's the point of doing it if we fail with an error? Originally the intent was "let those who are certain their workload replicates correctly with SRB, do it", but we are not allowing that anymore).
  • Analyze @@binlog_format and switch the statement to RBR binlogging when it uses a MyRocks table.
Comment by Sergei Petrunia [ 2019-06-15 ]

Following discussion with monty, considering a fix where ha_rocksdb::table_flags() will not return HA_BINLOG_STMT_CAPABLE flag. If we do that, the SQL layer will be able to switch to using RBR for statements that modify MyRocks tables.

Comment by Sergei Petrunia [ 2019-06-15 ]

A related variable:

rocksdb_unsafe_for_binlog
Description: Allowing statement based binary logging which may break consistency.
Commandline: --rocksdb-unsafe-for-binlog={0|1}
Scope: Global, Session
Dynamic: Yes
Data Type: boolean
Default Value: OFF

Comment by Sergei Petrunia [ 2019-06-15 ]

Currently, the check implements this logic:

SBR is allowed if:

  • @@rocksdb_unsafe_for_binlog is set
  • or, this is a slave thread

(this way, if the master had @@rocksdb_unsafe_for_binlog=1, the slave will be able to run this, even if the slave itself has @@rocksdb_unsafe_for_binlog=0, and is not aware that the master had this setting).

Comment by Sergei Petrunia [ 2019-06-15 ]

Branch: bb-10.2-mdev17045

Generated at Thu Feb 08 08:33:30 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.