summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2017-08-10 11:58:43 -0400
committerBenety Goh <benety@mongodb.com>2017-08-10 13:03:35 -0400
commitb8eb96c3c9c2ad2e0c4520785ba49cb9830b1a21 (patch)
treeed07f18aa65417eb0ad902f03358a554dd99dafb
parent54ce75ef7074fefe343114e2855426271f1f418e (diff)
downloadmongo-b8eb96c3c9c2ad2e0c4520785ba49cb9830b1a21.tar.gz
SERVER-30554 relax locking mode in applyOps when applying CRUD-only ops non-atomically
This allows concurrent applyOps commands to update the same collection on storage engines that support document level concurrency. (cherry picked from commit bca3f70566991afa2dfb38dc06494b0f6f04fffa)
-rw-r--r--jstests/replsets/apply_ops_concurrent_non_atomic_same_collection.js11
-rw-r--r--jstests/replsets/apply_ops_concurrent_non_atomic_same_db.js11
-rw-r--r--src/mongo/db/catalog/apply_ops.cpp5
3 files changed, 25 insertions, 2 deletions
diff --git a/jstests/replsets/apply_ops_concurrent_non_atomic_same_collection.js b/jstests/replsets/apply_ops_concurrent_non_atomic_same_collection.js
new file mode 100644
index 00000000000..004eeaaa52f
--- /dev/null
+++ b/jstests/replsets/apply_ops_concurrent_non_atomic_same_collection.js
@@ -0,0 +1,11 @@
+(function() {
+ 'use strict';
+
+ load('jstests/replsets/libs/apply_ops_concurrent_non_atomic.js');
+
+ new ApplyOpsConcurrentNonAtomicTest({
+ ns1: 'test.coll',
+ ns2: 'test.coll',
+ requiresDocumentLevelConcurrency: true,
+ }).run();
+}());
diff --git a/jstests/replsets/apply_ops_concurrent_non_atomic_same_db.js b/jstests/replsets/apply_ops_concurrent_non_atomic_same_db.js
new file mode 100644
index 00000000000..10f874382a5
--- /dev/null
+++ b/jstests/replsets/apply_ops_concurrent_non_atomic_same_db.js
@@ -0,0 +1,11 @@
+(function() {
+ 'use strict';
+
+ load('jstests/replsets/libs/apply_ops_concurrent_non_atomic.js');
+
+ new ApplyOpsConcurrentNonAtomicTest({
+ ns1: 'test.coll1',
+ ns2: 'test.coll2',
+ requiresDocumentLevelConcurrency: false,
+ }).run();
+}());
diff --git a/src/mongo/db/catalog/apply_ops.cpp b/src/mongo/db/catalog/apply_ops.cpp
index 5756a068917..28ca548c18f 100644
--- a/src/mongo/db/catalog/apply_ops.cpp
+++ b/src/mongo/db/catalog/apply_ops.cpp
@@ -158,7 +158,8 @@ Status _applyOps(OperationContext* opCtx,
invariant(opCtx->lockState()->isW());
status = repl::applyCommand_inlock(opCtx, opObj, true);
} else {
- Lock::DBLock dbWriteLock(opCtx->lockState(), nss.db(), MODE_X);
+ Lock::DBLock dbWriteLock(opCtx->lockState(), nss.db(), MODE_IX);
+ Lock::CollectionLock lock(opCtx->lockState(), nss.ns(), MODE_IX);
OldClientContext ctx(opCtx, ns);
status =
@@ -329,7 +330,7 @@ Status applyOps(OperationContext* opCtx,
// There's only one case where we are allowed to take the database lock instead of the global
// lock - no preconditions; only CRUD ops; and non-atomic mode.
if (!hasPrecondition && areOpsCrudOnly && !allowAtomic) {
- dbWriteLock.emplace(opCtx->lockState(), dbName, MODE_X);
+ dbWriteLock.emplace(opCtx->lockState(), dbName, MODE_IX);
} else {
globalWriteLock.emplace(opCtx->lockState());
}