使用 Python SDK 将同一分区键值范围内的多次读写组成一个原子操作,事务中的写入全部提交或全部丢弃。
前提条件
安装Tablestore Python SDK并初始化客户端。
-
已为数据表开启局部事务功能。
说明如果需要为已有数据表开启局部事务,或者确认数据表是否已开启该功能,请提交工单。
功能说明
局部事务作用于一个分区键值,隔离级别为读已提交(Read Committed)。事务内的请求通过同一个事务 ID 关联,按以下流程使用:
调用
start_local_transaction,传入分区键值并获取事务 ID。在事务内调用
get_row、put_row、update_row、delete_row、batch_write_row或get_range,并通过transaction_id携带事务 ID。调用
commit_transaction提交事务,使所有写入生效;或者调用abort_transaction丢弃事务,使所有写入失效。
def start_local_transaction(self, table_name, key)
def commit_transaction(self, transaction_id)
def abort_transaction(self, transaction_id)
以下示例为分区键值 device 创建局部事务,在事务内写入一行数据,然后提交事务。
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)
参数说明
局部事务包含以下关键参数。
|
名称 |
类型 |
说明 |
|
table_name(必选) |
|
数据表名称。 |
|
key(必选) |
|
创建局部事务时指定的分区键,只需包含第一个主键列的名称和值。 |
|
primary_key(必选) |
|
在事务内读写行时指定的完整主键,必须包含全部主键列。写请求的分区键值必须与 |
|
transaction_id(必选) |
|
|
使用限制
主键自增列与局部事务不能同时使用。
局部事务通过悲观锁控制并发。事务期间,分区键值对应的数据被加写锁,只有携带事务 ID 的写请求可以成功。
事务生命周期最长为 60 秒。两次操作间隔超过 60 秒时,事务超时,服务端自动丢弃。
同一事务 ID 同一时间只能用于一个请求,并发使用该 ID 的请求均失败。
事务内写请求的分区键值必须与创建事务时一致;读请求没有此限制。
单个事务最多写入 4 MB 数据。
事务内写入属性列时,如果未指定数据版本号,服务端在写入时生成版本号,而不是在提交时生成。
BatchWriteRowRequest携带事务 ID 时,所有行只能操作该事务对应的数据表。事务内没有写操作时,提交与丢弃效果相同,都会释放事务。
携带事务 ID 的读写请求失败不会结束事务。可以重试请求,或者主动丢弃事务。
场景示例
事务内读取一行
以下示例在局部事务内读取一行数据。对于只读事务,提交和丢弃效果相同。
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)
事务内批量写入多行
以下示例通过 set_transaction_id 在批量请求中携带事务 ID。所有行的分区键值必须与创建事务时一致。
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)