使用局部事务(分区键事务)可以指定某个分区键下的操作是原子的,该分区键下的操作要么全部成功要么全部失败,并且所提供的隔离级别为串行化。

使用局部事务只需要使用SyncClient#startLocalTransaction在指定的分区键下启动事务即可,并通过StartLocalTransactionResponse#getTransactionId来获取事务ID进行事务内的操作。当前支持局部事务的接口如下,所有继承了TxnRequest类的请求都支持事务操作:
  • DeleteRow
  • UpdateRow
  • BatchWriteRow
  • GetRange
  • PutRow
  • GetRow

构建Client

示例代码如下:
SyncClient syncClient = new SyncClient(
    endpoint,            // endpoint
    accessKeyId,         // access_key_id
    accessKeySecret,     // access_key_secret
    instanceName         // instance_name
)

事务的启动、提交与中止

  • 启动事务
    您可以通过SyncClient#startLocalTransaction来启动事务。
    // 局部事务需要指定一个分区键(第一列主键)
    PrimaryKey transactionPK = new PrimaryKey(Collections.singletonList(
        new PrimaryKeyColumn(PK_USER_ID, PrimaryKeyValue.fromString(userId))
    ));
    StartLocalTransactionRequest startTransactionRequest = new StartLocalTransactionRequest(TABLE_NAME, transactionPK);
    StartLocalTransactionResponse startTransactionResponse = syncClient.startLocalTransaction(startTransactionRequest);
    // 启动事务成功后会返回一个transactionId,任意实现了TxnRequest抽象类的请求都可以通过setTransactionId方法指定事务
    final String transactionId = startTransactionResponse.getTransactionID();
  • 提交事务
    // 提交事务,所有与该transactionId相关的写入操作将被永久地写入到Tablestore中
    syncClient.commitTransaction(new CommitTransactionRequest(transactionId));
  • 中止事务
    // 中止事务,所有与该transactionId相关的写入操作将被回滚
    syncClient.abortTransaction(new AbortTransactionRequest(transactionId));

通过事务ID执行操作

  • 通过事务执行写入操作
    以下为PutRow操作示例。在事务中的写操作必须要在启动事务的分区键下执行,否则会抛出异常。
    PutRowRequest typeAPutRequest = new PutRowRequest(new RowPutChange(
        TABLE_NAME,
        new PrimaryKey(Arrays.asList(
            new PrimaryKeyColumn(PK_USER_ID, PrimaryKeyValue.fromString(userId)),
            new PrimaryKeyColumn(PK_TYPE, PrimaryKeyValue.fromString(typeA))
        ))
    ).addColumn(COLUMN_CONTENT, ColumnValue.fromString("content_a")));
    // 设置事务ID,通过StartLocalTransactionResponse#getTransactionId获得
    typeAPutRequest.setTransactionId(transactionId);
    syncClient.putRow(typeAPutRequest);
    说明 GetRange、GetRow等读操作不能读取其他事务中已修改但是尚未提交的数据值。
  • 通过事务执行读取操作
    您可以在事务中执行一些读操作,例如最基本的“读取-修改-写回”,以下为GetRow操作示例。在事务下的GetRow操作必须在启动事务的分区键下执行。
    GetRowRequest getRowRequest = new GetRowRequest();
    SingleRowQueryCriteria singleRowQueryCriteria = new SingleRowQueryCriteria(
        TABLE_NAME,
        new PrimaryKey(Arrays.asList(
            new PrimaryKeyColumn(PK_USER_ID, PrimaryKeyValue.fromString(userId)),
            new PrimaryKeyColumn(PK_TYPE, PrimaryKeyValue.fromString(typeA))
        ))
    );
    singleRowQueryCriteria.setMaxVersions(1);
    getRowRequest.setRowQueryCriteria(singleRowQueryCriteria);
    // 需要设置事务ID
    getRowRequest.setTransactionId(transactionId);
    GetRowResponse getRowResponse = syncClient.getRow(getRowRequest);