Fix an assertion failure in range locking, locktree code. (#7938)
Summary: Fix this scenario: trx1> acquire shared lock on $key trx2> acquire shared lock on the same $key trx1> attempt to acquire a unique lock on $key. Lock acquisition will fail, and deadlock detection will start. It will call iterate_and_get_overlapping_row_locks() which will produce a list with two locks (shared locks by trx1 and trx2). However the code in lock_request::build_wait_graph() was not prepared to find the lock by the same transaction in the list of conflicting locks. Fix it to ignore it. (One may suggest to fix iterate_and_get_overlapping_row_locks() to not include locks by trx1. This is not a good idea, because that function is also used to report all locks currently held) Pull Request resolved: https://github.com/facebook/rocksdb/pull/7938 Reviewed By: zhichao-cao Differential Revision: D26529374 Pulled By: ajkr fbshipit-source-id: d89cbed008db1a97a8f2351b9bfb75310750d16a
This commit is contained in:
parent
ad25b1afb9
commit
c9878baa87
@ -136,6 +136,41 @@ TEST_F(RangeLockingTest, MyRocksLikeUpdate) {
|
||||
delete txn0;
|
||||
}
|
||||
|
||||
TEST_F(RangeLockingTest, UpgradeLockAndGetConflict) {
|
||||
WriteOptions write_options;
|
||||
TransactionOptions txn_options;
|
||||
auto cf = db->DefaultColumnFamily();
|
||||
Status s;
|
||||
std::string value;
|
||||
txn_options.lock_timeout= 10;
|
||||
|
||||
Transaction* txn0 = db->BeginTransaction(write_options, txn_options);
|
||||
Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
|
||||
|
||||
// Get the shared lock in txn0
|
||||
s = txn0->GetForUpdate(ReadOptions(), cf,
|
||||
Slice("a"), &value,
|
||||
false /*exclusive*/);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
|
||||
// Get the shared lock on the same key in txn1
|
||||
s = txn1->GetForUpdate(ReadOptions(), cf,
|
||||
Slice("a"), &value,
|
||||
false /*exclusive*/);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
|
||||
// Now, try getting an exclusive lock that overlaps with the above
|
||||
s = txn0->GetRangeLock(cf, Endpoint("a"), Endpoint("b"));
|
||||
ASSERT_TRUE(s.IsTimedOut());
|
||||
|
||||
txn0->Rollback();
|
||||
txn1->Rollback();
|
||||
|
||||
delete txn0;
|
||||
delete txn1;
|
||||
}
|
||||
|
||||
|
||||
TEST_F(RangeLockingTest, SnapshotValidation) {
|
||||
Status s;
|
||||
Slice key_slice = Slice("k");
|
||||
|
@ -187,8 +187,10 @@ static bool determine_conflicting_txnids(
|
||||
if (other_txnid != txnid) {
|
||||
if (conflicts) {
|
||||
if (other_txnid == TXNID_SHARED) {
|
||||
// Add all shared lock owners, except this transaction.
|
||||
for (TXNID shared_id : *lock.owners) {
|
||||
conflicts->add(shared_id);
|
||||
if (shared_id != txnid)
|
||||
conflicts->add(shared_id);
|
||||
}
|
||||
} else {
|
||||
conflicts->add(other_txnid);
|
||||
|
Loading…
x
Reference in New Issue
Block a user