facebook / rocksdb

A library that provides an embeddable, persistent key-value store for fast storage.
http://rocksdb.org
GNU General Public License v2.0
28.67k stars 6.33k forks source link

How TransactionDB replicates? #10285

Open willkozheng opened 2 years ago

willkozheng commented 2 years ago

Note: Please use Issues only for bug reports. For questions, discussions, feature requests, etc. post to dev group: https://groups.google.com/forum/#!forum/rocksdb or https://www.facebook.com/groups/rocksdb.dev

Expected behavior

rocksdb::WriteBatch write_batch(iter->GetBatch().writeBatchPtr->Data()); status = db->Write(rocksdb::WriteOptions(), &write_batch);

Write operation succeeded.

Actual behavior

Invalid argument: MarkNoop() handler not defined.

Steps to reproduce the behavior

`int main() { std::string db_dir = "./transaction_db_test/"; rocksdb::Options options; rocksdb::TransactionDBOptions toptions;

options.OptimizeForSmallDb();
options.create_if_missing = true;

rocksdb::TransactionDB *db = nullptr;
auto status = rocksdb::TransactionDB::Open(options, toptions, db_dir, &db);

if (!status.ok())
{
    std::cout << "Open failed " << status.ToString() << std::endl;
    return 0;
}

db->Put(rocksdb::WriteOptions(), "abc", "123");

std::unique_ptr<rocksdb::TransactionLogIterator> iter;
status = db->GetUpdatesSince(0, &iter, rocksdb::TransactionLogIterator::ReadOptions());

if (!status.ok())
{
    std::cout << "GetUpdatesSince failed " << status.ToString() << std::endl;
    return 0;
}

for (; iter->Valid(); iter->Next())
{
    rocksdb::WriteBatch write_batch(iter->GetBatch().writeBatchPtr->Data());

    status = db->Write(rocksdb::WriteOptions(), &write_batch);

    if (!status.ok())
    {
        std::cout << "Write failed " << status.ToString() << std::endl;
        return 0;
    }
}

return 0;

}`

riversand963 commented 2 years ago
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff7a8351d in __GI_abort () at abort.c:79
#2  0x00007ffff7a934c3 in __assert_fail_base (fmt=0x7ffff7c0b088 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0xda45e8 "s.ok()", file=file@entry=0xda3e08 "db/write_batch.cc", line=line@entry=689,
    function=function@entry=0xda41c8 "static rocksdb::Status rocksdb::WriteBatchInternal::Iterate(const rocksdb::WriteBatch*, rocksdb::WriteBatch::Handler*, size_t, size_t)") at assert.c:92
#3  0x00007ffff7a93533 in __GI___assert_fail (assertion=0xda45e8 "s.ok()", file=0xda3e08 "db/write_batch.cc", line=689,
    function=0xda41c8 "static rocksdb::Status rocksdb::WriteBatchInternal::Iterate(const rocksdb::WriteBatch*, rocksdb::WriteBatch::Handler*, size_t, size_t)") at assert.c:101
#4  0x00000000007fb80f in rocksdb::WriteBatchInternal::Iterate (wb=0x7ffff76395c0, handler=0x7fffffffd260, begin=12, end=22) at db/write_batch.cc:689
#5  0x00000000007fa46a in rocksdb::WriteBatch::Iterate (this=0x7ffff76395c0, handler=0x7fffffffd260) at db/write_batch.cc:477
#6  0x0000000000a3d4f7 in rocksdb::PessimisticTransaction::LockBatch (this=0x7ffff7642500, batch=0x7ffff76395c0, keys_to_unlock=0x7ffff7637700) at utilities/transactions/pessimistic_transaction.cc:912
#7  0x0000000000a3acbd in rocksdb::PessimisticTransaction::CommitBatch (this=0x7ffff7642500, batch=0x7ffff76395c0) at utilities/transactions/pessimistic_transaction.cc:445
#8  0x0000000000a4a78f in rocksdb::PessimisticTransactionDB::WriteWithConcurrencyControl (this=0x7ffff7742e00, opts=..., updates=0x7ffff76395c0) at ./utilities/transactions/pessimistic_transaction_db.h:91
#9  0x0000000000a48c15 in rocksdb::WriteCommittedTxnDB::Write (this=0x7ffff7742e00, opts=..., updates=0x7ffff76395c0) at utilities/transactions/pessimistic_transaction_db.cc:557
#10 0x0000000000423750 in rocksdb::TransactionTest_WalIterator_Test::TestBody (this=0x7ffff7699a00) at utilities/transactions/transaction_test.cc:286

The above is the stack trace. It shows that LockBatch uses a Handler to iterate through the write batch, but the handler does not implement MarkNoop(), thus hitting the error.

Below is my unit test, just for reference.

TEST_P(TransactionTest, WalIterator) {
  ASSERT_OK(ReOpen());
  ASSERT_OK(db->Put(WriteOptions(), "abc", "val"));

  std::unique_ptr<TransactionLogIterator> wal_iter;
  Status s = db->GetUpdatesSince(0, &wal_iter, TransactionLogIterator::ReadOptions());
  ASSERT_OK(s);

  for (; wal_iter->Valid(); wal_iter->Next()) {
    std::unique_ptr<WriteBatch> wb(wal_iter->GetBatch().writeBatchPtr);
    s = db->Write(WriteOptions(), wb.get());
    fprintf(stdout, "%s\n", s.ToString().c_str());
  }
}
riversand963 commented 2 years ago

Back to your question, have you considered using checkpoint/backupEngine for physical replication that directly copy files? Logical replication such as mysqldump has also been used by MySQL users.

riversand963 commented 2 years ago

This is an open-ended question rather than bug report. Closing for now after days of inactivity, feel free to reopen if needed.

UPDATE: We can think about fixing this.

KuDeSnik33ra commented 3 months ago

Any plans to support TransactDB replication?

KuDeSnik33ra commented 3 months ago

C:\vcpkg\buildtrees\rocksdb\src\v9.1.0-14667c6586.clean\utilities\transactions\pessimistic_transaction.cc, 912 assert kInvalidArgument as Handler has no MarkNoop overrided

KuDeSnik33ra commented 3 months ago

https://github.com/facebook/rocksdb/pull/12897