(The upstream task is: https://github.com/facebook/mysql-5.6/issues/800 )
Notes about how to use PerconaFT:
1. Data structures
1.1 A Global Lock Tree Manager object
1.2 A separate Lock Tree for each table
1.3 Each transaction keeps a track of ranges it is holding locks
2.1 Initializing the Lock Manager
2.2 Create Lock Tree for a table
2.3 Getting a lock
2.4 Releasing a lock.
2.5 Releasing all of the transaction's locks
There needs to be a global locktree_manager.
TokuDB uses a separate Lock Tree for each table db->i->lt.
Each transaction has a list of ranges that it is holding locks on. It is referred to like so
and is stored in this structure, together with a mutex to protect it:
The mutex is there, because the list may be modified by the lock escalation process (which may be invoked from a different thread).
(See toku_txn_destroy for how to free this)
Most functions that are mentioned here are from storage/tokudb/PerconaFT/src/, ydb_txn.cc, ydb_row_lock.cc - this is TokuDB's layer above the Lock Tree.
TokuDB does it when it opens a table's table_share. It is done like so:
Then, one needs to release it:
after the last release_lt call, the Lock Tree will be deleted (it is guaranteed to be empty).
(TODO: this is easy to arrange if Toku locks are invoked from MyRocks level. But if they are invoked from RocksDB, this is harder as RocksDB doesn't have any concept of tables or indexes. For start, we can pretend all keys are in one table)
This function has an example:
It is also possible to start an asynchronous lock request and then wait for it (see toku_db_start_range_lock, toku_db_wait_range_lock). We don't have a use for this it seems
Point locks are obtained by passing the same key as left_key and right_key.
TokuDB doesn't seem to release individual locks (all locks are held until transaction either commits or is aborted).
LockTree has a function to release locks from a specified range:
Besides calling that, one will need to
- wake up all waiting lock requests. release_locks doesn't wake them up. There is toku::lock_request::retry_all_lock_requests call which retries all pending requests (Which doesn't seem to be efficient... but maybe it is ok?)
- Remove the released lock from the list of locks it is holding (which is in db_txn_struct_i(txn)->lt_map). This is actually not essential because that list is only used for the purpose of releasing the locks when the transaction is finished.