Create and use transactions
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
This page describes how to create and use transactions, which were introduced in Aerospike Database 8.0.0. A transaction is an encapsulation of several commands, isolated from commands outside the transaction, and executed atomically.
To ensure strict serializability, transactions in Aerospike require CP consistency mode, known in Aerospike as the strong-consistency (SC) namespace configuration. A transaction can guarantee one of two outcomes: either all commands succeed together, or one or more commands fail, in which case you can request to roll back to the state of the records prior to the attempted transaction. No commands outside the transaction can see the state changes being created inside the transaction.
Transaction best practices
- Remember that transactions and single-record commands can be mixed in the same SC namespace.
- Make sure to call abort when your app gives up on a transaction. Not calling abort invokes unnecessary monitor activity, and leaves records “locked” for much longer than necessary.
- Use
batch-writesto write a group of independent records in a transaction. A batch is especially efficient inside a transaction. - Don’t mix expiration and non-durable deletes with transactions. This is a general recommendation for strong consistency namespaces.
- Pay attention to tombstone accumulation and tomb-raider configs.
- Do not truncate in a namespace with active transactions. If you must use transactions, see Pause and drain transactions before truncating for steps to first disable and drain existing transactions.
- Do not mix transactions with active-active XDR, unless you’re certain that you are not writing to the same records on both sides. Use stretch clusters (multi-site clustering) instead of XDR if you intend to use transactions this way.
Create a transaction
The following steps describe how to create a transaction, bind it to commands, and commit. A transaction object is attached to each command’s policy so the server can logically group related requests.
-
Create a transaction.
import com.aerospike.client.sdk.DataSet;DataSet demo = DataSet.of(namespace, set);// doInTransaction creates the transaction and runs the block in itsession.doInTransaction(txn -> {System.out.println("Begin txn: " + txn.getCurrentTransaction().getId());// Step 2's commands go here});from aerospike_sdk import DataSetdemo = DataSet.of(namespace, set_name)# The with block creates the transaction, commits it when the block ends,# and aborts it if the block raiseswith session.transaction() as txn:print(f"Begin txn: {txn.txn.id}")# Step 2's commands go here// Requires: use std::sync::Arc; use aerospike::Txn;let txn = Arc::new(Txn::new());println!("Begin txn: {}", txn.id());using Aerospike.Client;Txn txn = new Txn();Console.WriteLine("Begin txn: " + txn.Id);import as "github.com/aerospike/aerospike-client-go/v8"txn := as.NewTxn()fmt.Printf("Begin txn: %d\n", txn.Id())const Aerospike = require("aerospike");const txn = new Aerospike.Transaction();console.log("Begin txn:", txn.id);#include <inttypes.h>#include <stdio.h>#include <aerospike/as_txn.h>as_txn txn;as_txn_init(&txn);printf("Begin txn: %" PRIu64 "\n", txn.id);import com.aerospike.client.Txn;Txn txn = new Txn();System.out.println("Begin txn: " + txn.getId());import aerospiketxn = aerospike.Transaction()print(f"Begin txn: {txn.id}") -
Issue commands within a try block and attach the transaction to each command’s policy.
import com.aerospike.client.sdk.command.TxnStatus;TxnStatus status = session.doInTransaction(txn -> {// Commands on txn run in the transaction: there is no policy to settxn.upsert(demo.id(1)).bin("a").setTo("val1").execute();});with session.transaction() as txn:# Commands on txn run in the transaction: there is no policy to settxn.upsert(demo.id(1)).put({"a": "val1"}).execute()let mut wp = WritePolicy::default();wp.base_policy.txn = Some(txn.clone());let key = as_key!(namespace, set, 1);let result = client.put(&wp, &key, &[as_bin!("a", "val1")]).await;try{WritePolicy wp = client.WritePolicyDefault.Clone();wp.Txn = txn;Key key1 = new Key(ns, set, 1);client.Put(wp, key1, new Bin("a", "val1"));}// Requires: import as "github.com/aerospike/aerospike-client-go/v8"wp := as.NewWritePolicy(0, 0)wp.Txn = txnkey, _ := as.NewKey(namespace, set, 1)err := client.PutBins(wp, key, as.NewBin("a", "val1"))const policy = { txn };try {const key = new Aerospike.Key(ns, set, 1);await client.put(key, { a: "val1" }, {}, policy);}as_policy_write pw;as_policy_write_init(&pw);pw.base.txn = &txn;as_key key;as_key_init_int64(&key, namespace, set, 1);as_record rec;as_record_inita(&rec, 1);as_record_set_str(&rec, "a", "val1");aerospike_key_put(&as, &err, &pw, &key, &rec);as_record_destroy(&rec);try {WritePolicy wp = client.copyWritePolicyDefault();wp.txn = txn;Key key1 = new Key(namespace, set, 1);client.put(wp, key1, new Bin("a", "val1"));}try:wp = {"txn": txn}key = (namespace, set_name, 1)client.put(key, {"a": "val1"}, policy=wp) -
Commit the transaction.
// There is no commit call: doInTransaction commits when the block returns,// and returns the outcomeSystem.out.println("Commit txn: " + status);if (status == TxnStatus.ROLL_FORWARD_ABANDONED) {// Committed, but the writes stay provisional until the server rolls them forward}with session.transaction() as txn:txn.upsert(demo.id(1)).put({"a": "val1"}).execute()# The block commits when it ends; commit() commits now, and returns the outcomestatus = txn.commit()print(f"Commit txn: {status}")println!("Commit txn: {}", txn.id());client.commit(&txn).await?;Console.WriteLine("Commit txn: " + txn.Id);client.Commit(txn);fmt.Printf("Commit txn: %d\n", txn.Id())_, err = client.Commit(txn)if err != nil {log.Fatal(err)}console.log("Commit txn:", txn.id);await client.commit(txn);printf("Commit txn: %" PRIu64 "\n", txn.id);as_commit_status commit_status;aerospike_commit(&as, &err, &txn, &commit_status);as_txn_destroy(&txn);System.out.println("Commit txn: " + txn.getId());client.commit(txn);print(f"Commit txn: {txn.id}")client.commit(txn)
How to handle transaction errors
When an exception is thrown during a transaction, abort the transaction to roll back all changes and release locked records.
try { session.doInTransaction(txn -> { txn.upsert(demo.id(1)).bin("a").setTo("val1").execute(); });}catch (AerospikeException ae) { // doInTransaction has already aborted the transaction, and retried it while blocked if (ae.getResultCode() == ResultCode.MRT_BLOCKED) { // Transaction was still blocked after the retries — retry later } if (ae.getResultCode() == ResultCode.MRT_EXPIRED) { // Transaction expired before commit or abort — retry } throw ae;}from aerospike_sdk import ResultCodefrom aerospike_sdk.exceptions import AerospikeError
try: with session.transaction() as txn: txn.upsert(demo.id(1)).put({"a": "val1"}).execute()except AerospikeError as e: # The with block has already aborted the transaction if e.result_code == ResultCode.MRT_BLOCKED: # Transaction was blocked by another transaction — retry pass if e.result_code == ResultCode.MRT_EXPIRED: # Transaction expired before commit or abort — retry pass raiseif let Err(err) = result { client.abort(&txn).await?; if err.server_result_code() == Some(ResultCode::MrtBlocked) { // Transaction was blocked by another transaction — retry } if err.server_result_code() == Some(ResultCode::MrtExpired) { // Transaction expired before commit or abort — retry } return Err(err.into());}catch (AerospikeException ae){ client.Abort(txn); if (ae.Result == ResultCode.MRT_BLOCKED) { // Transaction was blocked by another transaction — retry } if (ae.Result == ResultCode.MRT_EXPIRED) { // Transaction expired before commit or abort — retry } throw;}catch (Exception){ client.Abort(txn); throw;}// Requires: import as "github.com/aerospike/aerospike-client-go/v8"// Requires: import "github.com/aerospike/aerospike-client-go/v8/types"if err != nil { client.Abort(txn) if asErr, ok := err.(*as.AerospikeError); ok { if asErr.ResultCode == types.MRT_BLOCKED { // Transaction was blocked by another transaction — retry } if asErr.ResultCode == types.MRT_EXPIRED { // Transaction expired before commit or abort — retry } } log.Fatal(err)}catch (err) { await client.abort(txn); if (err.code === Aerospike.status.MRT_BLOCKED) { // Transaction was blocked by another transaction — retry } if (err.code === Aerospike.status.MRT_EXPIRED) { // Transaction expired before commit or abort — retry } throw err;}if (err.code != AEROSPIKE_OK) { as_error abort_err; aerospike_abort(&as, &abort_err, &txn, NULL); if (err.code == AEROSPIKE_MRT_BLOCKED) { // Transaction was blocked by another transaction — retry } if (err.code == AEROSPIKE_MRT_EXPIRED) { // Transaction expired before commit or abort — retry } as_txn_destroy(&txn); return;}catch (AerospikeException ae) { client.abort(txn); if (ae.getResultCode() == ResultCode.MRT_BLOCKED) { // Transaction was blocked by another transaction — retry } if (ae.getResultCode() == ResultCode.MRT_EXPIRED) { // Transaction expired before commit or abort — retry } throw ae;}catch (Throwable t) { client.abort(txn); throw t;}except aerospike.exception.AerospikeError as ae: client.abort(txn) print(f"Error code: {ae.code}, message: {ae.msg}") raiseexcept Exception: client.abort(txn) raiseStatus codes
The following status codes can be returned during a transaction:
MRT_BLOCKED: The transaction was blocked by another transaction accessing the same record.MRT_EXPIRED: A command was sent after the transaction’s timeout.
if (ae.getResultCode() == ResultCode.MRT_BLOCKED) { // Transaction was still blocked after doInTransaction's retries — retry later}if (ae.getResultCode() == ResultCode.MRT_EXPIRED) { // Transaction expired before commit or abort — retry}if e.result_code == ResultCode.MRT_BLOCKED: # Transaction was blocked by another transaction — retry passif e.result_code == ResultCode.MRT_EXPIRED: # Transaction expired before commit or abort — retry passif err.server_result_code() == Some(ResultCode::MrtBlocked) { // Transaction was blocked by another transaction — retry}if err.server_result_code() == Some(ResultCode::MrtExpired) { // Transaction expired before commit or abort — retry}if (ae.Result == ResultCode.MRT_BLOCKED){ // Transaction was blocked by another transaction — retry}if (ae.Result == ResultCode.MRT_EXPIRED){ // Transaction expired before commit or abort — retry}// Requires: import "github.com/aerospike/aerospike-client-go/v8/types"if asErr.ResultCode == types.MRT_BLOCKED { // Transaction was blocked by another transaction — retry}if asErr.ResultCode == types.MRT_EXPIRED { // Transaction expired before commit or abort — retry}if (err.code === Aerospike.status.MRT_BLOCKED) { // Transaction was blocked by another transaction — retry}if (err.code === Aerospike.status.MRT_EXPIRED) { // Transaction expired before commit or abort — retry}if (err.code == AEROSPIKE_MRT_BLOCKED) { // Transaction was blocked by another transaction — retry}if (err.code == AEROSPIKE_MRT_EXPIRED) { // Transaction expired before commit or abort — retry}if (ae.getResultCode() == ResultCode.MRT_BLOCKED) { // Transaction was blocked by another transaction — retry}if (ae.getResultCode() == ResultCode.MRT_EXPIRED) { // Transaction expired before commit or abort — retry}if ae.code == 120: # MRT_BLOCKED # Transaction was blocked by another transaction — retry passif ae.code == 122: # MRT_EXPIRED # Transaction expired before commit or abort — retry passFailed commits
A commit may fail if the read verify step fails. Aerospike attempts to do the read, even if it is dirty during the command execution step. If the read is later determined to be invalid due to a version mismatch, the commit’s verify step fails: the client aborts the transaction and reports a verify failure. This indicates that another command outside the transaction changed the targeted record. The correct way to handle this situation is to retry the entire transaction.
There is also a chance that the transaction succeeds but the commit fails. An example of this would be if there is a problem updating the transaction monitor on the server. In these situations, Aerospike returns a commit exception, and if there is uncertainty about whether the transaction was committed fully, it sets the inDoubt flag to true.
To safely handle this situation, catch the exception from the commit and implement separate handling logic as follows.
import com.aerospike.client.sdk.command.CommitError;
try { session.doInTransaction(txn -> { // ... the transaction's commands ... });}catch (AerospikeException.Commit ce) { // doInTransaction does not retry a failed commit, and there is no commit to call again if (ce.getInDoubt()) { // Commit may or may not have completed — log records for later cleanup } else if (ce.error == CommitError.VERIFY_FAIL) { // Read was invalidated by an outside write — retry transaction } else { // Other commit failure — retry transaction }}from aerospike_sdk import CommitError, ResultCode
with session.transaction() as txn: ... # the transaction's commands
try: txn.commit() except CommitError as e: if e.in_doubt: # The transaction stays open after an in-doubt commit: commit again try: txn.commit() except CommitError as e2: if e2.in_doubt: # Recommit still in doubt — log records for later cleanup pass elif e.result_code == ResultCode.MRT_VERSION_MISMATCH: # Read was invalidated by an outside write — retry transaction pass else: # Other commit failure — retry transaction passif let Err(err) = client.commit(&txn).await { if err.in_doubt() { if let Err(err2) = client.commit(&txn).await { if err2.in_doubt() { // Recommit still in doubt — log records for later cleanup } } } else if matches!( err.kind(), ErrorKind::Commit { error_type: CommitErrorType::VerifyFail, .. } ) { // Read was invalidated by an outside write — retry transaction } else { // Other commit failure — retry transaction }}try{ client.Commit(txn);}catch (AerospikeException.Commit ce){ if (ce.InDoubt) { try { client.Commit(txn); } catch (AerospikeException.Commit ce2) { if (ce2.InDoubt) { // Recommit still in doubt — log records for later cleanup } } } else { if (ce.Error == CommitError.CommitErrorType.VERIFY_FAIL) { // Read was invalidated by an outside write — retry transaction } else { // Other commit failure — retry transaction } }}catch (Exception){ // Handle non-Aerospike exception}// Requires: import as "github.com/aerospike/aerospike-client-go/v8"_, err = client.Commit(txn)if err != nil { if txnErr, ok := err.(*as.TxnError); ok { if txnErr.InDoubt { _, err2 := client.Commit(txn) if err2 != nil { if txnErr2, ok := err2.(*as.TxnError); ok && txnErr2.InDoubt { // Recommit still in doubt — log records for later cleanup } } } else if txnErr.CommitError == as.CommitErrorVerifyFail { // Read was invalidated by an outside write — retry transaction } else { // Other commit failure — retry transaction } }}try { await client.commit(txn);} catch (err) { if (err.inDoubt) { try { await client.commit(txn); } catch (err2) { if (err2.inDoubt) { // Recommit still in doubt — log records for later cleanup } } } else { // Read invalidated by an outside write, or another commit failure — retry transaction }}as_commit_status commit_status;as_status status = aerospike_commit(&as, &err, &txn, &commit_status);
if (status != AEROSPIKE_OK) { if (err.in_doubt) { as_error err2; as_status status2 = aerospike_commit(&as, &err2, &txn, &commit_status); if (status2 != AEROSPIKE_OK && err2.in_doubt) { // Recommit still in doubt — log records for later cleanup } } else if (commit_status == AS_COMMIT_VERIFY_FAILED) { // Read was invalidated by an outside write — retry transaction } else { // Other commit failure — retry transaction }}as_txn_destroy(&txn);try { client.commit(txn);}catch (AerospikeException.Commit ce) { if (ce.getInDoubt()) { try { client.commit(txn); } catch (AerospikeException.Commit ce2) { if (ce2.getInDoubt()) { // Recommit still in doubt — log records for later cleanup } } } else { if (ce.error == CommitError.VERIFY_FAIL) { // Read was invalidated by an outside write — retry transaction } else { // Other commit failure — retry transaction } }}catch (Throwable t) { // Handle non-Aerospike exception}try: client.commit(txn)except aerospike.exception.AerospikeError as ae: if ae.in_doubt: try: client.commit(txn) except aerospike.exception.AerospikeError as ae2: if ae2.in_doubt: # Recommit still in doubt — log records for later cleanup pass else: # Read invalidated by an outside write, or another commit failure — retry transaction passexcept Exception: # Handle non-Aerospike exception passExamples
Setting a transaction timeout
You can set a timeout, in seconds, that limits how long the commands in the transaction can run. The timeout clock starts when the first write request for the transaction is submitted; read requests do not start the timeout clock. A command sent after the timeout fails with MRT_EXPIRED, and the server rolls back a transaction that has timed out, so commit before the timeout.
session.doInTransaction(txn -> { txn.getCurrentTransaction().setTimeout(20);
// Timeout clock starts after this operation txn.upsert(demo.id(1)).bin("a").setTo("val1").execute();
txn.upsert(demo.id(2)).bin("b").setTo("val2").execute();});with session.transaction() as txn: txn.txn.timeout = 20
# Timeout clock starts after this operation txn.upsert(demo.id(1)).put({"a": "val1"}).execute()
txn.upsert(demo.id(2)).put({"b": "val2"}).execute()// Requires: use std::time::Duration;let mut txn = Txn::new();txn.set_timeout(Duration::from_secs(20));let txn = Arc::new(txn);
let mut wp = WritePolicy::default();wp.base_policy.txn = Some(txn.clone());
// Timeout clock starts after this operationlet key1 = as_key!(namespace, set, 1);if let Err(err) = client.put(&wp, &key1, &[as_bin!("a", "val1")]).await { client.abort(&txn).await?; return Err(err.into());}
let key2 = as_key!(namespace, set, 2);if let Err(err) = client.put(&wp, &key2, &[as_bin!("b", "val2")]).await { client.abort(&txn).await?; return Err(err.into());}
client.commit(&txn).await?;Txn txn = new Txn();txn.Timeout = 20;
try{ WritePolicy wp = client.WritePolicyDefault.Clone(); wp.Txn = txn;
// Timeout clock starts after this operation Key key1 = new Key(ns, set, 1); client.Put(wp, key1, new Bin("a", "val1"));
Key key2 = new Key(ns, set, 2); client.Put(wp, key2, new Bin("b", "val2"));}catch (Exception){ client.Abort(txn); throw;}
client.Commit(txn);// Requires: import as "github.com/aerospike/aerospike-client-go/v8"txn := as.NewTxn()txn.SetTimeout(20 * time.Second)
wp := as.NewWritePolicy(0, 0)wp.Txn = txn
// Timeout clock starts after this operationkey1, _ := as.NewKey(namespace, set, 1)err := client.PutBins(wp, key1, as.NewBin("a", "val1"))if err != nil { client.Abort(txn) log.Fatal(err)}
key2, _ := as.NewKey(namespace, set, 2)err = client.PutBins(wp, key2, as.NewBin("b", "val2"))if err != nil { client.Abort(txn) log.Fatal(err)}
_, err = client.Commit(txn)const txn = new Aerospike.Transaction();txn.setTimeout(20);
const policy = { txn };
try { // Timeout clock starts after this operation await client.put(new Aerospike.Key(ns, set, 1), { a: "val1" }, {}, policy); await client.put(new Aerospike.Key(ns, set, 2), { b: "val2" }, {}, policy);} catch (err) { await client.abort(txn); throw err;}
await client.commit(txn);as_txn txn;as_txn_init(&txn);as_txn_set_timeout(&txn, 20);
as_policy_write pw;as_policy_write_init(&pw);pw.base.txn = &txn;
// Timeout clock starts after this operationas_key key1;as_key_init_int64(&key1, namespace, set, 1);as_record rec1;as_record_inita(&rec1, 1);as_record_set_str(&rec1, "a", "val1");aerospike_key_put(&as, &err, &pw, &key1, &rec1);as_record_destroy(&rec1);
as_key key2;as_key_init_int64(&key2, namespace, set, 2);as_record rec2;as_record_inita(&rec2, 1);as_record_set_str(&rec2, "b", "val2");aerospike_key_put(&as, &err, &pw, &key2, &rec2);as_record_destroy(&rec2);
as_commit_status commit_status;aerospike_commit(&as, &err, &txn, &commit_status);as_txn_destroy(&txn);Txn txn = new Txn();txn.setTimeout(20);
try { WritePolicy wp = client.copyWritePolicyDefault(); wp.txn = txn;
// Timeout clock starts after this operation Key key1 = new Key(namespace, set, 1); client.put(wp, key1, new Bin("a", "val1"));
Key key2 = new Key(namespace, set, 2); client.put(wp, key2, new Bin("b", "val2"));}catch (Throwable t) { client.abort(txn); throw t;}
client.commit(txn);txn = aerospike.Transaction()txn.timeout = 20
try: wp = {"txn": txn}
# Timeout clock starts after this operation client.put((namespace, set_name, 1), {"a": "val1"}, policy=wp) client.put((namespace, set_name, 2), {"b": "val2"}, policy=wp)except Exception: client.abort(txn) raise
client.commit(txn)Batched writes
For batched writes inside a transaction, attach the transaction to the batch policy.
import com.aerospike.client.sdk.RecordResult;
session.doInTransaction(txn -> { txn.upsert(demo.ids(1, 2, 3)) .bin("color").setTo("blue") .execute() // A batch reports a key's failure in its result: orThrow raises it, // so that doInTransaction aborts the transaction .forEach(RecordResult::orThrow);});with session.transaction() as txn: rows = txn.upsert(demo.ids(1, 2, 3)).put({"color": "blue"}).execute() # A batch reports a key's failure in its row, not as an exception: # record_or_raise raises it, so that the with block aborts the transaction for row in rows: row.record_or_raise()let txn = Arc::new(Txn::new());
let mut bp = BatchPolicy::default();bp.base_policy.txn = Some(txn.clone());
let bwp = BatchWritePolicy::default();let bin = as_bin!("color", "blue");let mut batch: Vec<BatchOperation> = [1, 2, 3] .into_iter() .map(|id| BatchOperation::write(&bwp, as_key!(namespace, set, id), vec![operations::put(&bin)])) .collect();
let result = client.batch(&bp, &mut batch).await;// A batch reports a key's failure in its record, not as an errorlet failed = batch .iter() .find_map(|op| op.result_code().filter(|rc| *rc != ResultCode::Ok));if result.is_err() || failed.is_some() { client.abort(&txn).await?; result?; return Err(format!("Batch write failed: {:?}", failed.unwrap()).into());}
client.commit(&txn).await?;Txn txn = new Txn();
BatchPolicy bp = new BatchPolicy(client.BatchPolicyDefault);bp.Txn = txn;
Key[] keys = new Key[]{ new Key(ns, set, 1), new Key(ns, set, 2), new Key(ns, set, 3)};
try{ BatchResults results = client.Operate(bp, null, keys, Operation.Put(new Bin("color", "blue")) ); // A batch reports a key's failure in its record, not as an exception foreach (BatchRecord br in results.records) { if (br.resultCode != ResultCode.OK) { throw new AerospikeException(br.resultCode); } }}catch (AerospikeException){ client.Abort(txn); throw;}
client.Commit(txn);// Requires: import as "github.com/aerospike/aerospike-client-go/v8"txn := as.NewTxn()
bp := as.NewBatchPolicy()bp.Txn = txn
key1, _ := as.NewKey(namespace, set, 1)key2, _ := as.NewKey(namespace, set, 2)key3, _ := as.NewKey(namespace, set, 3)
records := []as.BatchRecordIfc{ as.NewBatchWrite(nil, key1, as.PutOp(as.NewBin("color", "blue"))), as.NewBatchWrite(nil, key2, as.PutOp(as.NewBin("color", "blue"))), as.NewBatchWrite(nil, key3, as.PutOp(as.NewBin("color", "blue"))),}
err := client.BatchOperate(bp, records)if err == nil { // A batch reports a key's failure in its record, not as an error for _, r := range records { if r.BatchRec().Err != nil { err = r.BatchRec().Err break } }}if err != nil { client.Abort(txn) log.Fatal(err)}
_, err = client.Commit(txn)const txn = new Aerospike.Transaction();
const bp = new Aerospike.BatchPolicy({ txn });
const records = [ { type: Aerospike.batchType.BATCH_WRITE, key: new Aerospike.Key(ns, set, 1), ops: [Aerospike.operations.write("color", "blue")] }, { type: Aerospike.batchType.BATCH_WRITE, key: new Aerospike.Key(ns, set, 2), ops: [Aerospike.operations.write("color", "blue")] }, { type: Aerospike.batchType.BATCH_WRITE, key: new Aerospike.Key(ns, set, 3), ops: [Aerospike.operations.write("color", "blue")] },];
try { const results = await client.batchWrite(records, bp); // A batch reports a key's failure in its record, not as an error const failed = results.find((r) => r.status !== Aerospike.status.OK); if (failed) { throw new Error(`Batch write failed: status ${failed.status}`); }} catch (err) { await client.abort(txn); throw err;}
await client.commit(txn);as_txn txn;as_txn_init(&txn);
as_policy_batch pb;as_policy_batch_init(&pb);pb.base.txn = &txn;
as_operations ops1, ops2, ops3;as_operations_inita(&ops1, 1);as_operations_add_write_str(&ops1, "color", "blue");as_operations_inita(&ops2, 1);as_operations_add_write_str(&ops2, "color", "blue");as_operations_inita(&ops3, 1);as_operations_add_write_str(&ops3, "color", "blue");
as_batch_records records;as_batch_records_inita(&records, 3);
as_batch_write_record* bw;bw = as_batch_write_reserve(&records);as_key_init_int64(&bw->key, namespace, set, 1);bw->ops = &ops1;
bw = as_batch_write_reserve(&records);as_key_init_int64(&bw->key, namespace, set, 2);bw->ops = &ops2;
bw = as_batch_write_reserve(&records);as_key_init_int64(&bw->key, namespace, set, 3);bw->ops = &ops3;
as_status status = aerospike_batch_write(&as, &err, &pb, &records);
// A batch reports a key's failure in its record, not as an errorfor (uint32_t i = 0; status == AEROSPIKE_OK && i < records.list.size; i++) { as_batch_base_record* r = as_vector_get(&records.list, i); status = r->result;}as_batch_records_destroy(&records);
if (status != AEROSPIKE_OK) { as_error abort_err; aerospike_abort(&as, &abort_err, &txn, NULL);}else { as_commit_status commit_status; aerospike_commit(&as, &err, &txn, &commit_status);}as_txn_destroy(&txn);Txn txn = new Txn();
BatchPolicy bp = client.copyBatchPolicyDefault();bp.txn = txn;
BatchWritePolicy bwp = client.copyBatchWritePolicyDefault();
Key[] keys = new Key[] { new Key(namespace, set, 1), new Key(namespace, set, 2), new Key(namespace, set, 3)};
try { BatchResults results = client.operate(bp, bwp, keys, Operation.put(new Bin("color", "blue")) ); // A batch reports a key's failure in its record, not as an exception for (BatchRecord br : results.records) { if (br.resultCode != ResultCode.OK) { throw new AerospikeException(br.resultCode); } }}catch (AerospikeException ae) { client.abort(txn); throw ae;}
client.commit(txn);from aerospike_helpers.batch import records as brfrom aerospike_helpers.operations import operations as op
txn = aerospike.Transaction()
keys = [ (namespace, set_name, 1), (namespace, set_name, 2), (namespace, set_name, 3),]
try: bp = {"txn": txn} batch_records = br.BatchRecords( [br.Write(key, [op.write("color", "blue")]) for key in keys] ) client.batch_write(batch_records, policy_batch=bp) # A batch reports a key's failure in its record, not as an exception for rec in batch_records.batch_records: if rec.result != 0: raise RuntimeError(f"Batch write failed: result {rec.result}")except Exception: client.abort(txn) raise
client.commit(txn)Put, get, and delete in the same transaction
The following example shows multiple commands tied to the same transaction.
session.doInTransaction(txn -> { txn.upsert(demo.id(1)).bin("a").setTo("val1").execute();
Record rec = txn.query(demo.id(3)).execute().getFirstRecord();
txn.delete(demo.id(3)).withDurableDelete().execute();});with session.transaction() as txn: txn.upsert(demo.id(1)).put({"a": "val1"}).execute()
rec = txn.get(demo.id(3))
txn.delete(demo.id(3)).with_durable_delete().execute()let txn = Arc::new(Txn::new());
let mut wp = WritePolicy::default();wp.base_policy.txn = Some(txn.clone());let key1 = as_key!(namespace, set, 1);if let Err(err) = client.put(&wp, &key1, &[as_bin!("a", "val1")]).await { client.abort(&txn).await?; return Err(err.into());}
let mut rp = ReadPolicy::default();rp.base_policy.txn = Some(txn.clone());let key2 = as_key!(namespace, set, 3);let _rec = match client.get(&rp, &key2, Bins::All).await { Ok(rec) => rec, Err(err) => { client.abort(&txn).await?; return Err(err.into()); }};
let mut dp = WritePolicy::default();dp.base_policy.txn = Some(txn.clone());dp.durable_delete = true;if let Err(err) = client.delete(&dp, &key2).await { client.abort(&txn).await?; return Err(err.into());}
client.commit(&txn).await?;Txn txn = new Txn();
try{ WritePolicy wp = client.WritePolicyDefault.Clone(); wp.Txn = txn;
Key key1 = new Key(ns, set, 1); client.Put(wp, key1, new Bin("a", "val1"));
Policy p = client.ReadPolicyDefault.Clone(); p.Txn = txn;
Key key2 = new Key(ns, set, 3); Record rec = client.Get(p, key2);
WritePolicy dp = client.WritePolicyDefault.Clone(); dp.Txn = txn; dp.durableDelete = true; client.Delete(dp, key2);}catch (Exception){ client.Abort(txn); throw;}
client.Commit(txn);// Requires: import as "github.com/aerospike/aerospike-client-go/v8"txn := as.NewTxn()
wp := as.NewWritePolicy(0, 0)wp.Txn = txn
key1, _ := as.NewKey(namespace, set, 1)err := client.PutBins(wp, key1, as.NewBin("a", "val1"))if err != nil { client.Abort(txn) log.Fatal(err)}
rp := as.NewPolicy()rp.Txn = txn
key2, _ := as.NewKey(namespace, set, 3)rec, err := client.Get(rp, key2)if err != nil { client.Abort(txn) log.Fatal(err)}_ = rec
dp := as.NewWritePolicy(0, 0)dp.Txn = txndp.DurableDelete = true_, err = client.Delete(dp, key2)if err != nil { client.Abort(txn) log.Fatal(err)}
_, err = client.Commit(txn)const txn = new Aerospike.Transaction();const policy = { txn };
try { await client.put(new Aerospike.Key(ns, set, 1), { a: "val1" }, {}, policy);
const rec = await client.get(new Aerospike.Key(ns, set, 3), policy);
const dp = new Aerospike.WritePolicy({ txn, durableDelete: true }); await client.remove(new Aerospike.Key(ns, set, 3), dp);} catch (err) { await client.abort(txn); throw err;}
await client.commit(txn);as_txn txn;as_txn_init(&txn);
as_policy_write pw;as_policy_write_init(&pw);pw.base.txn = &txn;
as_key key1;as_key_init_int64(&key1, namespace, set, 1);as_record rec1;as_record_inita(&rec1, 1);as_record_set_str(&rec1, "a", "val1");aerospike_key_put(&as, &err, &pw, &key1, &rec1);as_record_destroy(&rec1);
as_policy_read pr;as_policy_read_init(&pr);pr.base.txn = &txn;
as_key key2;as_key_init_int64(&key2, namespace, set, 3);as_record* p_rec = NULL;aerospike_key_get(&as, &err, &pr, &key2, &p_rec);if (p_rec) as_record_destroy(p_rec);
as_policy_remove pd;as_policy_remove_init(&pd);pd.base.txn = &txn;pd.durable_delete = true;aerospike_key_remove(&as, &err, &pd, &key2);
as_commit_status commit_status;aerospike_commit(&as, &err, &txn, &commit_status);as_txn_destroy(&txn);Txn txn = new Txn();
try { WritePolicy wp = client.copyWritePolicyDefault(); wp.txn = txn;
Key key1 = new Key(namespace, set, 1); client.put(wp, key1, new Bin("a", "val1"));
Policy p = client.copyReadPolicyDefault(); p.txn = txn;
Key key2 = new Key(namespace, set, 3); Record rec = client.get(p, key2);
WritePolicy dp = client.copyWritePolicyDefault(); dp.txn = txn; dp.durableDelete = true; client.delete(dp, key2);}catch (Throwable t) { client.abort(txn); throw t;}
client.commit(txn);txn = aerospike.Transaction()
try: wp = {"txn": txn} client.put((namespace, set_name, 1), {"a": "val1"}, policy=wp)
rp = {"txn": txn} _, _, bins = client.get((namespace, set_name, 3), policy=rp)
dp = {"txn": txn, "durable_delete": True} client.remove((namespace, set_name, 3), policy=dp)except Exception: client.abort(txn) raise
client.commit(txn)