-
Type: Improvement
-
Resolution: Won't Do
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
Database.create_collection runs the listCollections command to check if the collection already exists on the server and if so raises CollectionInvalid:
>>> client.admin.create_collection('test') Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'admin'), 'test') >>> client.admin.create_collection('test') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymongo/database.py", line 365, in create_collection raise CollectionInvalid("collection %s already exists" % name) pymongo.errors.CollectionInvalid: collection test already exists
But the server already returns an error if the collection already exists (since at least MongoDB 2.6):
>>> client.server_info()['version'] '2.6.12' >>> client.admin.command('create', 'test') {'ok': 1.0} >>> client.admin.command('create', 'test') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymongo/database.py", line 614, in command codec_options, session=session, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymongo/database.py", line 514, in _command client=self.__client) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymongo/pool.py", line 579, in command unacknowledged=unacknowledged) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymongo/network.py", line 150, in command parse_write_concern_error=parse_write_concern_error) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymongo/helpers.py", line 155, in _check_command_response raise OperationFailure(msg % errmsg, code, response) pymongo.errors.OperationFailure: collection already exists
Additionally this client side check introduces a time-of-check to time-of-use race condition where:
- Thread A runs db.create_collection('test')
- Thread A runs listCollections and sees that the collection does not exist
- Meanwhile, Thread B runs db.create_collection('test') to completion
- db.test now exists on the server
- Thread A resumes and runs the create command which fails with OperationFailure: collection already exists
Instead we should just rely on the server to decide.
We can even make this change backwards compatible by catching the OperationFailure: collection already exists error and raising CollectionInvalid: collection test already exists instead.
- depends on
-
SERVER-60064 Make create command idempotent on mongod
- Closed
- is related to
-
PYTHON-3298 Add flag to create_collection to skip listCollections pre-check
- Closed
-
PYTHON-2030 Collection and index creation in multi-doc txns
- Closed
- related to
-
SERVER-33276 Creation of already existing collection on a sharded cluster should be an error
- Closed