dropDatabase runs in two steps. First it drops all collections. Then it waits for those drops to replicate (releasing locks). Lastly, it reacquires locks and finalizes the dropDatabase which among other things, writes the dropDatabase oplog entry.
To manage concurrency control when locks are released, the command sets a drop pending flag. This flag is to prevent collections from being created until the dropDatabase is completed.
However, that flag does not prevent a second, concurrent dropDatabase from being accepted. A second dropDatabase will not have any collections to drop and fast-paths into writing a dropDatabase oplog entry and deleting the database object.
One manifestation of this bug is, when adding a third client that creates a collection, an illegal update chain can be created (an untimestamped write).
| DropDB Client 1 | DropDB Client2 | CreateColl | |------------------------------------------+-------------------------------------+----------------------------------------------------| | Grabs locks | | | | Sets dropPending true | | | | Drops Coll db.A (replicates) [1] | | | | Releases locks | | | | Waits for replication of Drop A | | | | | Grabs locks | | | | Sets dropPending true | | | | Drops nothing | | | | Finishes dropDatabase | | | | Writes dropDatabase oplog entry [2] | | | | Deletes DB object | | | | Releases locks | | | | | Gets locks | | | | Creates db.B with a new DB object (replicates) [3] | | | | Releases locks | | Gets locks | | | | Acquires the new DB object | | | | Finishes dropDatabase | | | | Drops db.B (unreplicated, untimestamped) | | | | Writes dropDatabase oplog entry [4] | | |
Results in the oplog entries:
- Drop `db.A`
- DropDatabase `db`.
- Create `db.B`
- DropDatabase `db`.
- is depended on by
-
SERVER-42497 Detect/log unintentional untimestamped writes to catalog table
- Closed