summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiangyu Yao <xiangyu.yao@mongodb.com>2018-10-20 20:56:37 -0400
committerXiangyu Yao <xiangyu.yao@mongodb.com>2018-10-25 01:49:11 -0400
commit3aebbb51ed5fe82601f601916251c5f892a59467 (patch)
treea8055a4e574bf9e4100dd62355a6f080f225599d
parent67a110a2bfb42aaca26933c4f5fffbf5edb418cf (diff)
downloadmongo-3aebbb51ed5fe82601f601916251c5f892a59467.tar.gz
SERVER-37313 Secondary foreground index build should take Database X rather than Global X lock
(cherry picked from commit e7bed9bdcb376d5a06dce6228047309e8481f9cf)
-rw-r--r--src/mongo/db/repl/oplog.cpp10
-rw-r--r--src/mongo/db/repl/sync_tail.cpp8
2 files changed, 13 insertions, 5 deletions
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 2ad84d776e9..94477d111d8 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -231,6 +231,11 @@ void createIndexForApplyOps(OperationContext* opCtx,
const NamespaceString& indexNss,
IncrementOpsAppliedStatsFn incrementOpsAppliedStats,
OplogApplication::Mode mode) {
+ // Lock the database if it's not locked.
+ boost::optional<Lock::DBLock> dbLock;
+ if (!opCtx->lockState()->isDbLockedForMode(indexNss.db(), MODE_X)) {
+ dbLock.emplace(opCtx, indexNss.db(), MODE_X);
+ }
// Check if collection exists.
Database* db = DatabaseHolder::getDatabaseHolder().get(opCtx, indexNss.ns());
auto indexCollection = db ? db->getCollection(opCtx, indexNss) : nullptr;
@@ -1525,6 +1530,7 @@ Status applyCommand_inlock(OperationContext* opCtx,
return {ErrorCodes::InvalidNamespace, "invalid ns: " + std::string(nss.ns())};
}
{
+ Lock::DBLock lock(opCtx, nss.db(), MODE_IS);
Database* db = DatabaseHolder::getDatabaseHolder().get(opCtx, nss.ns());
if (db && !db->getCollection(opCtx, nss) && db->getViewCatalog()->lookup(opCtx, nss.ns())) {
return {ErrorCodes::CommandNotSupportedOnView,
@@ -1549,10 +1555,6 @@ Status applyCommand_inlock(OperationContext* opCtx,
<< redact(op));
}
- // Applying commands in repl is done under Global W-lock, so it is safe to not
- // perform the current DB checks after reacquiring the lock.
- invariant(opCtx->lockState()->isW());
-
// Parse optime from oplog entry unless we are applying this command in standalone or on a
// primary (replicated writes enabled).
OpTime opTime;
diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp
index 0356a80e1d9..b611f8b8305 100644
--- a/src/mongo/db/repl/sync_tail.cpp
+++ b/src/mongo/db/repl/sync_tail.cpp
@@ -387,7 +387,13 @@ Status SyncTail::syncApply(OperationContext* opCtx,
return writeConflictRetry(opCtx, "syncApply_command", nss.ns(), [&] {
// a command may need a global write lock. so we will conservatively go
// ahead and grab one here. suboptimal. :-(
- Lock::GlobalWrite globalWriteLock(opCtx);
+ boost::optional<Lock::GlobalWrite> globalWriteLock;
+
+ const StringData commandName(op["o"].embeddedObject().firstElementFieldName());
+ // SERVER-37313: createIndex does not need to take the Global X lock.
+ if (commandName != "createIndexes") {
+ globalWriteLock.emplace(opCtx);
+ }
// special case apply for commands to avoid implicit database creation
Status status = applyCommand_inlock(opCtx, op, oplogApplicationMode);