Batch Transaction
- It is done on same partition.
- Have Atomicity, means one fail all fails.
- Creating a batch requires a partition key.
Code
TransactionalBatch batch = container.CreateTransactionalBatch(partitionKey)
.CreateItem(saddle)
.CreateItem(handlebar)
.ReplaceItem(id, product); //Replace
const saddle = { id: "0120", name: "Worn Saddler", categoryId: "9603ca6c-9e28-4a02-9194-51cdb7fea816" };
const handlebar = { id: "012A", name: "Rusty Handlebarr", categoryId: "9603ca6c-9e28-4a02-9194-51cdb7fea816" };
const helmet = { id: "012C", name: "New Helmet", categoryId: "2202234-9e28-4a02-9194-51cdb7fea816" };
const partitionKey = saddle.categoryId;
// Create items, the partitionKey is optional it will not insert and not IMPORTANT!
const batchOperations = [
{ operationType: "Create", resourceBody: saddle, partitionKey: saddle.categoryId },
// { operationType: "Create", resourceBody: helmet, partitionKey: helmet.categoryId }, // This fails and will throw error
{ operationType: "Create", resourceBody: handlebar, partitionKey: handlebar.categoryId }
];
const batchResponse = await container.items.batch(batchOperations, partitionKey); // IMPORTANT: Must have this parameter partitionKey
console.log("Batch create response:", batchResponse);
Status
- Operations are http, so to view status:
- StatusCode
- Etag
- To view all see (batchResponse.IsSuccessStatusCode), to view each either forLoop or use GetOperationResultAtIndex(0).
response.result.forEach((operationResult, index) => {
const { statusCode, requestCharge, resourceBody } = operationResult;
console.log(`Operation ${index + 1}: Status code: ${statusCode}, Request charge: ${requestCharge}, Resource: ${JSON.stringify(resourceBody)}`);
});
Product product = response.Resource;
string eTag = response.ETag;
Concurrency Control
To avoid concurrency update, use accessCondition
await container.items.upsert(product, {
accessCondition: { type: "IfMatch", condition: eTag }
});
ItemRequestOptions options = new ItemRequestOptions { IfMatchEtag = eTag };
await container.UpsertItemAsync<Product>(product, partitionKey, requestOptions: options);
Limit
- The Azure Cosmos DB request size limit constrains the size of the transactional batch payload to not exceed 2 MB, and the maximum execution time is 5 seconds.
- There's a current limit of 100 operations per transactional batch to ensure the performance is as expected and within SLAs.
-
There are no support for cross-partition.
-
Note: While the 2MB limit is for the entire Transactional Batch payload as a whole, it effectively means an individual item within that batch can monopolize that payload size. However, the standard maximum item size individually still strictly remains 2MB.
Common Error Status
| Error Code | Summary | Description |
|---|---|---|
| 424 | Failed dependency | One of the batch item fail, all other will fail hence it just return 424 |
| 409 | Conflict | An item have different partition key value than the. batch partition key |
| 404 | Not found | Only for ReadItem and item not found |
Denormalizing table
(See partitioning design to look back on this comment)
The potential of having 2 types (e.g. customer and sales order) in the same container is important for bulk transaction. If there are 2 seperate containers it's not possible to do a bulk transaction.
Given that both sales order and customer have customerId as the partition key, we can update both together. Because customers and sales orders reside in the same logical partition, you can insert the new sales order and update the customer document within a transaction. There are two ways to implement transactions in Azure Cosmos DB: by using stored procedures or by using a feature called transactional batch, which is available in both .NET and Java SDKs.