diff options
author | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2018-10-20 20:56:37 -0400 |
---|---|---|
committer | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2018-10-25 01:49:11 -0400 |
commit | 3aebbb51ed5fe82601f601916251c5f892a59467 (patch) | |
tree | a8055a4e574bf9e4100dd62355a6f080f225599d | |
parent | 67a110a2bfb42aaca26933c4f5fffbf5edb418cf (diff) | |
download | mongo-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.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/sync_tail.cpp | 8 |
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); |