diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 5e4152f7dcf..e77de87cf2c 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -4416,6 +4416,49 @@ static int rocksdb_done_func(void *const p) { error = 1; } + /* + MariaDB: When the plugin is unloaded with UNINSTALL SONAME command, some + connections may still have Rdb_transaction objects. + + These objects are not genuine transactions (as SQL layer makes sure that + a plugin that is being unloaded has no open tables), they are empty + Rdb_transaction objects that were left there to save on object + creation/deletion. + + Go through the list and delete them. + */ + { + class Rdb_trx_deleter: public Rdb_tx_list_walker { + public: + std::set rdb_trxs; + + void process_tran(const Rdb_transaction *const tx) override { + /* + Check if the transaction is really empty. We only check + non-WriteBatch-based transactions, because there is no easy way to + check WriteBatch-based transactions. + */ + if (!tx->is_writebatch_trx()) { + const auto tx_impl = static_cast(tx); + DBUG_ASSERT(tx_impl); + if (tx_impl->get_rdb_trx()) + DBUG_ASSERT(0); + } + rdb_trxs.insert((Rdb_transaction*)tx); + }; + } deleter; + + Rdb_transaction::walk_tx_list(&deleter); + + for (std::set::iterator it= deleter.rdb_trxs.begin(); + it != deleter.rdb_trxs.end(); + ++it) + { + // When a transaction is deleted, it removes itself from s_tx_list. + delete *it; + } + } + /* destructors for static objects can be called at _exit(), but we want to free the memory at dlclose() diff --git a/storage/rocksdb/mysql-test/rocksdb/r/mariadb_plugin.result b/storage/rocksdb/mysql-test/rocksdb/r/mariadb_plugin.result new file mode 100644 index 00000000000..bb06c4be2e5 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/r/mariadb_plugin.result @@ -0,0 +1,12 @@ +# +# MDEV-14843: Assertion `s_tx_list.size() == 0' failed in myrocks::Rdb_transaction::term_mutex +# +INSTALL SONAME 'ha_rocksdb'; +CREATE TABLE t1 (i INT) ENGINE=RocksDB; +insert into t1 values (1); +connect con1,localhost,root,,; +connection con1; +insert into test.t1 values (1); +connection default; +DROP TABLE t1; +UNINSTALL SONAME 'ha_rocksdb'; diff --git a/storage/rocksdb/mysql-test/rocksdb/t/mariadb_plugin-master.opt b/storage/rocksdb/mysql-test/rocksdb/t/mariadb_plugin-master.opt new file mode 100644 index 00000000000..0f0a3ef33e5 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/t/mariadb_plugin-master.opt @@ -0,0 +1 @@ +--default-storage-engine=myisam --plugin-load='' --ignore-db-dirs=#rocksdb diff --git a/storage/rocksdb/mysql-test/rocksdb/t/mariadb_plugin.test b/storage/rocksdb/mysql-test/rocksdb/t/mariadb_plugin.test new file mode 100644 index 00000000000..303c4a5e0f9 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/t/mariadb_plugin.test @@ -0,0 +1,21 @@ +--source include/have_log_bin.inc +--source include/have_binlog_format_row.inc + +--echo # +--echo # MDEV-14843: Assertion `s_tx_list.size() == 0' failed in myrocks::Rdb_transaction::term_mutex +--echo # + +INSTALL SONAME 'ha_rocksdb'; + +CREATE TABLE t1 (i INT) ENGINE=RocksDB; +insert into t1 values (1); + +connect (con1,localhost,root,,); +connection con1; +insert into test.t1 values (1); + +connection default; + +# Cleanup +DROP TABLE t1; +UNINSTALL SONAME 'ha_rocksdb';