Use Tablestore SDK for Python to group reads and writes for one partition key value into an atomic operation whose writes are all committed or all discarded.
Prerequisites
Install the Tablestore SDK for Python and initialize a client.
-
Local transactions are enabled for the table.
NoteTo enable local transactions for an existing table or check whether the feature is enabled, submit a ticket.
Function description
A local transaction is scoped to one partition key value and uses the Read Committed isolation level. Requests in the transaction share a transaction ID. Use a local transaction as follows:
Call
start_local_transactionwith the partition key value to obtain a transaction ID.Call
get_row,put_row,update_row,delete_row,batch_write_row, orget_rangein the transaction and pass the ID intransaction_id.Call
commit_transactionto commit all writes orabort_transactionto discard all writes.
def start_local_transaction(self, table_name, key)
def commit_transaction(self, transaction_id)
def abort_transaction(self, transaction_id)
The following example starts a local transaction for the partition key value device, writes a row, and commits the transaction.
table_name = "example_table"
partition_key = [("partition", "device")]
transaction_id = client.start_local_transaction(table_name, partition_key)
primary_key = [("partition", "device"), ("id", 1)]
row = Row(primary_key, [("status", "online")])
condition = Condition(RowExistenceExpectation.IGNORE)
client.put_row(
table_name,
row,
condition,
transaction_id=transaction_id,
)
client.commit_transaction(transaction_id)
Parameters
A local transaction contains the following key parameters.
|
Name |
Type |
Description |
|
table_name (required) |
|
The name of the table. |
|
key (required) |
|
The partition key used to start the local transaction. Specify only the name and value of the first primary key column. |
|
primary_key (required) |
|
The complete primary key used to read or write a row in the transaction. Specify all primary key columns. For writes, the partition key value must match |
|
transaction_id (required) |
|
The local transaction ID returned by |
Limits
Local transactions are not compatible with auto-increment primary key columns.
Local transactions use pessimistic locking. During a transaction, a write lock is held on data for the partition key value, and only writes that carry the transaction ID can succeed.
A transaction has a maximum lifetime of 60 seconds. If two consecutive operations are more than 60 seconds apart, the transaction times out and the server discards it.
A transaction ID can be used by only one request at a time. Concurrent requests that share the ID all fail.
Every write in a transaction must use the partition key value that started the transaction. Reads have no such restriction.
A single transaction can write up to 4 MB of data.
If an attribute column write does not specify a data version, the server generates the version at write time, not at commit time.
When a
BatchWriteRowRequestcarries a transaction ID, all rows must target the table on which the transaction was started.If a transaction contains no writes, commit and abort have the same effect and both release the transaction.
A failed read or write that carries a transaction ID does not end the transaction. Retry the request or abort the transaction explicitly.
Examples
Read a row in a transaction
The following example reads a row in a local transaction. For a read-only transaction, commit and abort have the same effect.
table_name = "example_table"
partition_key = [("partition", "device")]
transaction_id = client.start_local_transaction(table_name, partition_key)
primary_key = [("partition", "device"), ("id", 1)]
consumed, return_row, next_token = client.get_row(
table_name,
primary_key,
transaction_id=transaction_id,
)
print(return_row.primary_key, return_row.attribute_columns)
client.commit_transaction(transaction_id)
Batch write rows in a transaction
The following example calls set_transaction_id to include the transaction ID in a batch request. The partition key value of every row must match the value used to start the transaction.
table_name = "example_table"
partition_key = [("partition", "device")]
transaction_id = client.start_local_transaction(table_name, partition_key)
condition = Condition(RowExistenceExpectation.IGNORE)
row_items = [
PutRowItem(Row([("partition", "device"), ("id", 2)], [("status", "online")]), condition),
PutRowItem(Row([("partition", "device"), ("id", 3)], [("status", "offline")]), condition),
]
request = BatchWriteRowRequest()
request.add(TableInBatchWriteRowItem(table_name, row_items))
request.set_transaction_id(transaction_id)
response = client.batch_write_row(request)
if response.is_all_succeed():
client.commit_transaction(transaction_id)
else:
client.abort_transaction(transaction_id)