How does MongoDB deal with transactional conflicts?
up vote
1
down vote
favorite
If both two threads do read and write a same document:
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
result = collection.find(clientSession, keyOfDoc);
if (result blah blah blah) {
// Change the doc
collection.insertOne(clientSession, doc);
}
clientSession.commitTransaction();
}
From the purpose of the transaction, one of the thread should get the edited version of another thread.
However, when both threads start transaction they both acquired a read lock, and then read the doc. Both the threads got the old version of the doc. and when they need to write the doc, they try to acquire write locks, which will make the transaction not atomic.
Another situation is the write-write conflict.
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
collection.insertOne(clientSession, docDifferent);
collection.insertOne(clientSession, docSame);
clientSession.commitTransaction();
}
Both thread first acquires write locks of different documents, and then they acquire the write lock of the same document, as it is another transactional conflict.
What level of lock does MongoDB use? I know they use instance level before version 2.2 while transactions are supported since 4.0. If MongoDB doesn't use database level locks, How does MongoDB deal with transactional conflicts? Or if it uses database level locks, how does it deal with read-write conflicts?
mongodb concurrency locking
add a comment |
up vote
1
down vote
favorite
If both two threads do read and write a same document:
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
result = collection.find(clientSession, keyOfDoc);
if (result blah blah blah) {
// Change the doc
collection.insertOne(clientSession, doc);
}
clientSession.commitTransaction();
}
From the purpose of the transaction, one of the thread should get the edited version of another thread.
However, when both threads start transaction they both acquired a read lock, and then read the doc. Both the threads got the old version of the doc. and when they need to write the doc, they try to acquire write locks, which will make the transaction not atomic.
Another situation is the write-write conflict.
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
collection.insertOne(clientSession, docDifferent);
collection.insertOne(clientSession, docSame);
clientSession.commitTransaction();
}
Both thread first acquires write locks of different documents, and then they acquire the write lock of the same document, as it is another transactional conflict.
What level of lock does MongoDB use? I know they use instance level before version 2.2 while transactions are supported since 4.0. If MongoDB doesn't use database level locks, How does MongoDB deal with transactional conflicts? Or if it uses database level locks, how does it deal with read-write conflicts?
mongodb concurrency locking
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
If both two threads do read and write a same document:
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
result = collection.find(clientSession, keyOfDoc);
if (result blah blah blah) {
// Change the doc
collection.insertOne(clientSession, doc);
}
clientSession.commitTransaction();
}
From the purpose of the transaction, one of the thread should get the edited version of another thread.
However, when both threads start transaction they both acquired a read lock, and then read the doc. Both the threads got the old version of the doc. and when they need to write the doc, they try to acquire write locks, which will make the transaction not atomic.
Another situation is the write-write conflict.
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
collection.insertOne(clientSession, docDifferent);
collection.insertOne(clientSession, docSame);
clientSession.commitTransaction();
}
Both thread first acquires write locks of different documents, and then they acquire the write lock of the same document, as it is another transactional conflict.
What level of lock does MongoDB use? I know they use instance level before version 2.2 while transactions are supported since 4.0. If MongoDB doesn't use database level locks, How does MongoDB deal with transactional conflicts? Or if it uses database level locks, how does it deal with read-write conflicts?
mongodb concurrency locking
If both two threads do read and write a same document:
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
result = collection.find(clientSession, keyOfDoc);
if (result blah blah blah) {
// Change the doc
collection.insertOne(clientSession, doc);
}
clientSession.commitTransaction();
}
From the purpose of the transaction, one of the thread should get the edited version of another thread.
However, when both threads start transaction they both acquired a read lock, and then read the doc. Both the threads got the old version of the doc. and when they need to write the doc, they try to acquire write locks, which will make the transaction not atomic.
Another situation is the write-write conflict.
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
collection.insertOne(clientSession, docDifferent);
collection.insertOne(clientSession, docSame);
clientSession.commitTransaction();
}
Both thread first acquires write locks of different documents, and then they acquire the write lock of the same document, as it is another transactional conflict.
What level of lock does MongoDB use? I know they use instance level before version 2.2 while transactions are supported since 4.0. If MongoDB doesn't use database level locks, How does MongoDB deal with transactional conflicts? Or if it uses database level locks, how does it deal with read-write conflicts?
mongodb concurrency locking
mongodb concurrency locking
edited Nov 8 at 6:25
asked Nov 8 at 6:11
iry
234
234
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
I found some references in the MongoDB Manual that solved my own question.
What type of locking does MongoDB use?
MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).
MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.
Restricted Operations
The following operations are not allowed in multi-document transactions:
Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.
The listCollections and listIndexes commands and their helper methods are also excluded.
Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.
For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.
Retry Transaction
The individual write operations inside the
transaction are not retryable, regardless of whether retryWrites is
set totrue.
If an operation encounters an error, the returned error may have an
errorLabels array field. If the error is a transient error, the
errorLabels array field contains "TransientTransactionError" as an
element and the transaction as a whole can be retried.
Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.
You can simply use this method(modified from the manual example):
public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
while (true) {
try {
return transactional.call();
} catch (MongoException ex) {
if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
}
}
}
See editions for more languages in the manual ;)!
References
Transactions — MongoDB Manual
FAQ: Concurrency — MongoDB Manual
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
I found some references in the MongoDB Manual that solved my own question.
What type of locking does MongoDB use?
MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).
MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.
Restricted Operations
The following operations are not allowed in multi-document transactions:
Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.
The listCollections and listIndexes commands and their helper methods are also excluded.
Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.
For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.
Retry Transaction
The individual write operations inside the
transaction are not retryable, regardless of whether retryWrites is
set totrue.
If an operation encounters an error, the returned error may have an
errorLabels array field. If the error is a transient error, the
errorLabels array field contains "TransientTransactionError" as an
element and the transaction as a whole can be retried.
Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.
You can simply use this method(modified from the manual example):
public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
while (true) {
try {
return transactional.call();
} catch (MongoException ex) {
if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
}
}
}
See editions for more languages in the manual ;)!
References
Transactions — MongoDB Manual
FAQ: Concurrency — MongoDB Manual
add a comment |
up vote
0
down vote
I found some references in the MongoDB Manual that solved my own question.
What type of locking does MongoDB use?
MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).
MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.
Restricted Operations
The following operations are not allowed in multi-document transactions:
Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.
The listCollections and listIndexes commands and their helper methods are also excluded.
Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.
For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.
Retry Transaction
The individual write operations inside the
transaction are not retryable, regardless of whether retryWrites is
set totrue.
If an operation encounters an error, the returned error may have an
errorLabels array field. If the error is a transient error, the
errorLabels array field contains "TransientTransactionError" as an
element and the transaction as a whole can be retried.
Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.
You can simply use this method(modified from the manual example):
public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
while (true) {
try {
return transactional.call();
} catch (MongoException ex) {
if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
}
}
}
See editions for more languages in the manual ;)!
References
Transactions — MongoDB Manual
FAQ: Concurrency — MongoDB Manual
add a comment |
up vote
0
down vote
up vote
0
down vote
I found some references in the MongoDB Manual that solved my own question.
What type of locking does MongoDB use?
MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).
MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.
Restricted Operations
The following operations are not allowed in multi-document transactions:
Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.
The listCollections and listIndexes commands and their helper methods are also excluded.
Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.
For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.
Retry Transaction
The individual write operations inside the
transaction are not retryable, regardless of whether retryWrites is
set totrue.
If an operation encounters an error, the returned error may have an
errorLabels array field. If the error is a transient error, the
errorLabels array field contains "TransientTransactionError" as an
element and the transaction as a whole can be retried.
Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.
You can simply use this method(modified from the manual example):
public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
while (true) {
try {
return transactional.call();
} catch (MongoException ex) {
if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
}
}
}
See editions for more languages in the manual ;)!
References
Transactions — MongoDB Manual
FAQ: Concurrency — MongoDB Manual
I found some references in the MongoDB Manual that solved my own question.
What type of locking does MongoDB use?
MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).
MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.
Restricted Operations
The following operations are not allowed in multi-document transactions:
Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.
The listCollections and listIndexes commands and their helper methods are also excluded.
Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.
For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.
Retry Transaction
The individual write operations inside the
transaction are not retryable, regardless of whether retryWrites is
set totrue.
If an operation encounters an error, the returned error may have an
errorLabels array field. If the error is a transient error, the
errorLabels array field contains "TransientTransactionError" as an
element and the transaction as a whole can be retried.
Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.
You can simply use this method(modified from the manual example):
public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
while (true) {
try {
return transactional.call();
} catch (MongoException ex) {
if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
}
}
}
See editions for more languages in the manual ;)!
References
Transactions — MongoDB Manual
FAQ: Concurrency — MongoDB Manual
answered Nov 9 at 5:12
iry
234
234
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53202345%2fhow-does-mongodb-deal-with-transactional-conflicts%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown