diff options
author | Lingzhi Deng <lingzhi.deng@mongodb.com> | 2019-05-07 17:57:46 -0400 |
---|---|---|
committer | Lingzhi Deng <lingzhi.deng@mongodb.com> | 2019-05-14 17:31:19 -0400 |
commit | 7353674ed14d39305b2640805524bb5cfe61cbd1 (patch) | |
tree | 0d574a0f69c5f9579be24fb40c70f59455775c44 /src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h | |
parent | 00f77c5e43270301bfea2ef8ed330b9d6f59cd3e (diff) | |
download | mongo-7353674ed14d39305b2640805524bb5cfe61cbd1.tar.gz |
SERVER-40936: Add an invariant that we do not get a prepare conflict while holding a global, database, or collection MODE_S lock
Diffstat (limited to 'src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h')
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h b/src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h index f3031a3105d..b9778c55978 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h @@ -69,6 +69,25 @@ int wiredTigerPrepareConflictRetry(OperationContext* opCtx, F&& f) { CurOp::get(opCtx)->debug().additiveMetrics.incrementPrepareReadConflicts(1); wiredTigerPrepareConflictLog(attempts); + const auto lockerInfo = opCtx->lockState()->getLockerInfo(boost::none); + invariant(lockerInfo); + for (const auto& lock : lockerInfo->locks) { + const auto type = lock.resourceId.getType(); + // If a user operation on secondaries acquires a lock in MODE_S and then blocks on a prepare + // conflict with a prepared transaction, deadlock will occur at the commit time of the + // prepared transaction when it attempts to reacquire (since locks were yielded on + // secondaries) an IX lock that conflicts with the MODE_S lock held by the user operation. + // User operations that acquire MODE_X locks and block on prepare conflicts could lead to + // the same problem. However, user operations on secondaries should never hold MODE_X locks. + // Since prepared transactions will not reacquire RESOURCE_MUTEX / RESOURCE_METADATA locks + // at commit time, these lock types are safe. Therefore, invariant here that we do not get a + // prepare conflict while holding a global, database, or collection MODE_S lock (or MODE_X + // lock for completeness). + if (type == RESOURCE_GLOBAL || type == RESOURCE_DATABASE || type == RESOURCE_COLLECTION) + invariant(lock.mode != MODE_S && lock.mode != MODE_X, + str::stream() << lock.resourceId.toString() << " in " << modeName(lock.mode)); + } + if (MONGO_FAIL_POINT(WTSkipPrepareConflictRetries)) { // Callers of wiredTigerPrepareConflictRetry() should eventually call wtRCToStatus() via // invariantWTOK() and have the WT_ROLLBACK error bubble up as a WriteConflictException. |