Tablestore SDK for Go を使用して、単一のパーティションキー値に対してローカルトランザクションを実行できます。これにより、トランザクション内のすべての書き込みが、まとめてコミットまたは破棄されます。分離レベルはリードコミッティドです。
前提条件
-
Tablestore SDK for Go をインストールし、クライアントを初期化します。ローカルトランザクションにはバージョン 1.7.8 以降が必要です。最新バージョンの使用を推奨します。
-
対象のテーブルでローカルトランザクションが有効になっている必要があります。テーブル作成時に
EnableLocalTxnを設定できます。既存のテーブルでローカルトランザクションが有効かどうかを確認、または有効化するには、チケットを送信するか。
説明
ローカルトランザクションは、1 つのパーティションキー値に制限されます。トランザクション内の読み取りと書き込みは、同じトランザクション ID を共有します。ワークフローは次の 3 段階です:
-
パーティションキー値を指定して
StartLocalTransactionを呼び出し、ローカルトランザクションを作成してトランザクション ID を取得します。 -
トランザクション内で
GetRow、PutRow、UpdateRow、DeleteRow、BatchWriteRow、またはGetRangeを呼び出し、各リクエストにトランザクション ID を含めます。 -
すべての変更を適用するには
CommitTransactionを、トランザクションとすべての変更を破棄するにはAbortTransactionを呼び出します。
func (client *TableStoreClient) StartLocalTransaction(request *StartLocalTransactionRequest) (*StartLocalTransactionResponse, error)
func (client *TableStoreClient) CommitTransaction(request *CommitTransactionRequest) (*CommitTransactionResponse, error)
func (client *TableStoreClient) AbortTransaction(request *AbortTransactionRequest) (*AbortTransactionResponse, error)
次のサンプルは、user-a のパーティションキー値に対してローカルトランザクションを作成し、トランザクション内で行を書き込み、トランザクションをコミットします。
partitionKey := &tablestore.PrimaryKey{}
partitionKey.AddPrimaryKeyColumn("user_id", "user-a")
startResponse, err := client.StartLocalTransaction(
&tablestore.StartLocalTransactionRequest{
TableName: "example_table",
PrimaryKey: partitionKey,
},
)
if err != nil {
log.Fatal(err)
}
transactionID := startResponse.TransactionId
rowKey := &tablestore.PrimaryKey{}
rowKey.AddPrimaryKeyColumn("user_id", "user-a")
rowKey.AddPrimaryKeyColumn("record_id", int64(1))
change := &tablestore.PutRowChange{
TableName: "example_table",
PrimaryKey: rowKey,
TransactionId: transactionID,
}
change.AddColumn("status", "created")
change.SetCondition(tablestore.RowExistenceExpectation_IGNORE)
_, err = client.PutRow(&tablestore.PutRowRequest{PutRowChange: change})
if err != nil {
_, _ = client.AbortTransaction(
&tablestore.AbortTransactionRequest{TransactionId: transactionID},
)
log.Fatal(err)
}
_, err = client.CommitTransaction(
&tablestore.CommitTransactionRequest{TransactionId: transactionID},
)
if err != nil {
log.Fatal(err)
}
パラメータ
ローカルトランザクションの作成
StartLocalTransactionRequest には、次のパラメータが含まれます。
|
名前 |
型 |
説明 |
|
TableName (必須) |
|
テーブル名。 |
|
PrimaryKey (必須) |
|
トランザクションのスコープを定義するパーティションキー値。テーブルの先頭のプライマリキー列のみを指定してください。 |
トランザクション内のデータ操作
トランザクションで使用する場合、PutRowChange、UpdateRowChange、DeleteRowChange、SingleRowQueryCriteria、および RangeRowQueryCriteria には、次の共通パラメータが含まれます。
|
名前 |
型 |
説明 |
|
TransactionId (必須) |
|
|
ローカルトランザクションのコミットまたはアボート
CommitTransactionRequest と AbortTransactionRequest には、次のパラメータが含まれます。
|
名前 |
型 |
説明 |
|
TransactionId (必須) |
|
コミットまたはアボートするローカルトランザクション ID。 |
レスポンス
StartLocalTransactionResponse には、次のビジネス情報が含まれます。
|
フィールド |
型 |
説明 |
|
|
|
新しいローカルトランザクション ID。データ操作およびトランザクションのコミットまたはアボートに使用します。 |
制限事項
-
自動インクリメント主キーとローカルトランザクションは併用できません。
-
ローカルトランザクションは、同時実行制御に悲観的ロックを使用します。トランザクション中は、該当するパーティションキー値に対する書き込みがロックされます。トランザクション ID を付与した書き込みリクエストのみが成功します。サーバーは、トランザクションがコミット、アボート、またはタイムアウトされると、書き込みロックを解除します。
-
トランザクションの存続時間は最大 60 秒です。2 つの操作の間隔が 60 秒を超えると、サーバーは自動的にトランザクションをアボートします。
-
ローカルトランザクションの作成リクエストがタイムアウトした場合でも、サーバー側ではすでにトランザクションが作成されている可能性があります。別のトランザクションを作成する前に、トランザクションがタイムアウトするまで待機してください。
-
未コミットのローカルトランザクションが無効になる場合があります。この場合は、トランザクション内の操作をリトライしてください。
-
同時に 1 つのリクエストのみがトランザクション ID を使用できます。同じトランザクション ID を使用する並行リクエストは失敗します。
-
トランザクション内の書き込みリクエストでは、トランザクション作成時に使用したパーティションキー値を使用する必要があります。読み取りリクエストにはこの制限は適用されません。
-
トランザクション内で
BatchWriteRowを使用して行を書き込む場合、リクエスト内のすべての行は、そのトランザクションが作成されたテーブルに属している必要があります。 -
トランザクションで書き込めるデータ量は最大 4 MB です。データ量は、通常の書き込みリクエストの計算ルールに基づいて累積されます。
-
属性列にバージョンが指定されていない場合、サーバーは、トランザクションのコミット時ではなく、データの書き込み時に通常の書き込みルールに基づいてバージョンを生成します。
-
読み取りまたは書き込みが失敗しても、トランザクションは無効になりません。リクエストをリトライするか、トランザクションをアボートできます。
例
ローカルトランザクションでの行の読み取り
次のサンプルは、既存のローカルトランザクションで行を読み取ります。読み取り専用トランザクションの場合、コミットとアボートの効果は同じです。どちらもトランザクションを解放します。
criteria := &tablestore.SingleRowQueryCriteria{
TableName: "example_table",
PrimaryKey: rowKey,
MaxVersion: 1,
TransactionId: transactionID,
}
response, err := client.GetRow(
&tablestore.GetRowRequest{SingleRowQueryCriteria: criteria},
)
if err != nil {
log.Fatal(err)
}
fmt.Println(response.Columns)
_, err = client.CommitTransaction(
&tablestore.CommitTransactionRequest{TransactionId: transactionID},
)
if err != nil {
log.Fatal(err)
}