Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-17045

MyRocks tables cannot be updated when binlog_format=MIXED.

Details

    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.

      Attachments

        Activity

          psergei Sergei Petrunia added a comment - - edited

          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.

          psergei Sergei Petrunia added a comment - - edited 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.

          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.
          psergei Sergei Petrunia added a comment - 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.

          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.

          psergei Sergei Petrunia added a comment - 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.
          psergei Sergei Petrunia added a comment - - edited

          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
          

          psergei Sergei Petrunia added a comment - - edited 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
          psergei Sergei Petrunia added a comment - - edited

          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).

          psergei Sergei Petrunia added a comment - - edited 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).

          Branch: bb-10.2-mdev17045

          psergei Sergei Petrunia added a comment - Branch: bb-10.2-mdev17045

          People

            psergei Sergei Petrunia
            psergei Sergei Petrunia
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Git Integration

                Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.