すべてのプロダクト
Search
ドキュメントセンター

Tablestore:ローカル トランザクション

最終更新日:Dec 28, 2024

データテーブルのローカル トランザクション機能を有効にすると、指定されたパーティションキー値に基づいてローカル トランザクションを作成し、ローカル トランザクション内のデータに対して読み取りおよび書き込み操作を実行できます。ローカル トランザクション機能を使用して、1 つ以上の行を読み書きするアトミック操作を実行できます。

ローカル トランザクションを使用して、同じパーティションキーを共有するデータに対する操作がすべて成功するか、すべて失敗するかを指定できます。ローカル トランザクションの分離レベルは Read Committed です。

前提条件

  • OTSClient インスタンスが初期化されています。詳細については、OTSClient インスタンスの初期化を参照してください。

  • データテーブルが作成され、データがデータテーブルに書き込まれています。

手順

  1. StartLocalTransaction オペレーションを呼び出して、指定されたパーティションキー値に基づいてローカル トランザクションを作成し、ローカル トランザクション ID を取得します。

  2. ローカル トランザクション内のデータを読み書きします。

    GetRow、PutRow、DeleteRow、UpdateRow、BatchWriteRow、および GetRange オペレーションを呼び出して、ローカル トランザクション内のデータに対する操作を実行できます。

  3. CommitTransaction オペレーションを呼び出してローカル トランザクションをコミットするか、AbortTransaction オペレーションを呼び出してローカル トランザクションを中止します。

使用上の注意

  • 自動インクリメント主キー列機能とローカル トランザクション機能を同時に使用することはできません。

  • ローカル トランザクションでの同時実行操作を制御するために、悲観的ロックが使用されます。

  • ローカル トランザクションの有効期間は最大 60 秒です。

    60 秒以内にローカル トランザクションがコミットまたは中止されない場合、Tablestore サーバーはローカル トランザクションがタイムアウトしたと判断し、トランザクションを中止します。

  • タイムアウトエラーが返された場合でも、Tablestore サーバーでトランザクションが作成される場合があります。この場合、作成されたトランザクションがタイムアウトした後に、トランザクション作成リクエストを再送信できます。

  • ローカル トランザクションがコミットされていない場合、無効になる可能性があります。この場合、このトランザクションの操作を再試行してください。

  • ローカル トランザクション内のデータに対して書き込み操作が実行されない場合、コミット操作と中止操作は同じ効果があります。

  • Tablestore は、ローカル トランザクション内のデータに対する読み取りおよび書き込み操作に次の制限を課します:

    • ローカル トランザクション ID を使用して、トランザクションの作成に使用されたパーティションキー値に基づいて指定された範囲外のデータにアクセスすることはできません。

    • 同じトランザクション内のすべての書き込みリクエストのパーティションキー値は、トランザクションの作成に使用されたパーティションキー値と同じである必要があります。この制限は、読み取りリクエストには適用されません。

    • ローカル トランザクションは、一度に 1 つのリクエストのみで使用できます。ローカル トランザクションが使用中の場合、同じローカル トランザクション ID を使用する他の操作は失敗します。

    • ローカル トランザクション内のデータに対する 2 つの連続した読み取りまたは書き込み操作の最大間隔は 60 秒です。

      60 秒以上ローカル トランザクション内のデータに対して読み取りまたは書き込み操作が実行されない場合、Tablestore サーバーはトランザクションがタイムアウトしたと判断し、トランザクションを中止します。

    • 各トランザクションに最大 4 MB のデータを書き込むことができます。各トランザクションに書き込まれるデータ量は、通常の書き込みリクエストと同じ方法で計算されます。

    • セルにバージョン番号を指定しない場合、Tablestore サーバーは、トランザクションのコミット時ではなく、セルがトランザクションに書き込まれたときに、通常の方法でセルにバージョン番号を自動的に割り当てます。

    • BatchWriteRow リクエストにローカル トランザクション ID が含まれている場合、リクエスト内のすべての行は、ローカル トランザクション ID と一致するテーブルにのみ書き込むことができます。

    • ローカル トランザクションを使用する場合、ローカル トランザクションが作成されたパーティションキー値のデータに書き込みロックが追加されます。ローカル トランザクション ID を含み、ローカル トランザクション内のデータを書き込むために開始された書き込みリクエストのみが成功します。他の非トランザクションリクエスト、または他のローカル トランザクションの ID を含み、ローカル トランザクション内のデータを書き込むために開始された書き込みリクエストは失敗します。トランザクションがコミットまたは中止された場合、またはトランザクションがタイムアウトした場合、ローカル トランザクション内のデータはロック解除されます。

    • ローカル トランザクション ID を持つ読み取りまたは書き込みリクエストが拒否された場合でも、ローカル トランザクションは有効なままです。再試行ルールを指定してリクエストを再送信するか、トランザクションを中止することができます。

パラメーター

パラメーター

必須

説明

TableName

はい

データテーブルの名前。

PrimaryKey

はい

データテーブルの主キー。

  • ローカル トランザクションを作成するときは、パーティションキー値を指定する必要があります。

  • ローカル トランザクション内のデータを読み書きするときは、すべての主キー列の値を指定する必要があります。

TransactionId

はい

ローカル トランザクションを一意に識別するローカル トランザクション ID。

ローカル トランザクション内のデータを読み書きするときは、ローカル トランザクション ID を指定する必要があります。

ローカル トランザクション機能を使用してデータの行を書き込む

次のサンプルコードは、テーブル内の指定されたパーティションキー値に基づいてローカル トランザクションを作成し、ローカル トランザクション内にデータの行を書き込む方法の例を示しています。ローカル トランザクション内にデータの行が書き込まれた場合は、トランザクションをコミットします。そうでない場合は、トランザクションを破棄します。

func transactionPutRow(client *tablestore.TableStoreClient, tableName string) {
    // ローカル トランザクションのパーティションキー値を指定します。パーティションキーは最初の主キー列です。
    transPk := new(tablestore.PrimaryKey)
    transPk.AddPrimaryKeyColumn("pk1", "pk1value")
    trans := &tablestore.StartLocalTransactionRequest{
        TableName:  tableName,
        PrimaryKey: transPk,
    }
    response, err := client.StartLocalTransaction(trans)
    if err != nil {
        fmt.Println("トランザクションの作成に失敗しました", err)
        return
    }
    // ローカル トランザクション ID を取得します。
    transId := response.TransactionId

    putPk := new(tablestore.PrimaryKey)
    putPk.AddPrimaryKeyColumn("pk1", "pk1value")
    putPk.AddPrimaryKeyColumn("pk2", int64(4))
    putRowChange := &tablestore.PutRowChange{
        TableName:  tableName,
        PrimaryKey: putPk,
    }
    putRowChange.AddColumn("col1", "col1data1")
    putRowChange.AddColumn("col2", int64(3))
    putRowChange.AddColumn("col3", []byte("test"))
    putRowChange.SetCondition(tablestore.RowExistenceExpectation_IGNORE)
    // ローカル トランザクション ID を指定します。これは、StartLocalTransactionResponse.TransactionId を使用して取得できます。
    putRowChange.TransactionId = transId
    putRowRequest := &tablestore.PutRowRequest{
        PutRowChange: putRowChange,
    }
    _, err = client.PutRow(putRowRequest)
    if err != nil {
        // ローカル トランザクション内にデータの行を書き込むことができない場合は、ローカル トランザクションを破棄します。この場合、ローカル トランザクション内のすべてのデータ変更は、データテーブル内のデータに適用されません。
        fmt.Println("putrow はエラーで失敗しました:", err)
        request := &tablestore.AbortTransactionRequest{
            TransactionId: transId,
        }
        abortResponse, err := client.AbortTransaction(request)
        if err != nil {
            fmt.Println("トランザクションの中止はエラーで失敗しました:", err)
        } else {
            fmt.Println("トランザクションの中止が完了しました。RequestId は", abortResponse.RequestId)
        }
    } else {
        // ローカル トランザクション内にデータの行が書き込まれた場合は、ローカル トランザクションをコミットします。この場合、ローカル トランザクション内のすべてのデータ変更が有効になります。ローカル トランザクションを破棄して、ローカル トランザクション内のすべてのデータ変更を無効にすることができます。
        fmt.Println("putrow が完了しました")
        request := &tablestore.CommitTransactionRequest{
            TransactionId: transId,
        }
        commitResponse, err := client.CommitTransaction(request)
        if err != nil {
            fmt.Println("トランザクションのコミットはエラーで失敗しました:", err)
        } else {
            fmt.Println("トランザクションのコミットが完了しました。RequestId は", commitResponse.RequestId)
        }
    }
}

ローカル トランザクション機能を使用してデータの行を読み取る

次のサンプルコードは、テーブル内の指定されたパーティションキー値に基づいてローカル トランザクションを作成し、ローカル トランザクション内のデータの行を読み取る方法の例を示しています:

func transactionGetRow(client *tablestore.TableStoreClient, tableName string) {
    // ローカル トランザクションのパーティションキー値を指定します。パーティションキーは最初の主キー列です。
    transPk := new(tablestore.PrimaryKey)
    transPk.AddPrimaryKeyColumn("pk1", "pk1value")
    trans := &tablestore.StartLocalTransactionRequest{
        TableName:  tableName,
        PrimaryKey: transPk,
    }
    response, err := client.StartLocalTransaction(trans)
    if err != nil {
        fmt.Println("トランザクションの作成に失敗しました", err)
        return
    }
    // ローカル トランザクション ID を取得します。
    transId := response.TransactionId

    // データを読み取ります。
    getRowPk := new(tablestore.PrimaryKey)
    getRowPk.AddPrimaryKeyColumn("pk1", "pk1value")
    getRowPk.AddPrimaryKeyColumn("pk2", int64(18))
    criteria := &tablestore.SingleRowQueryCriteria{
        PrimaryKey: getRowPk,
        TableName:  tableName,
        // 最新バージョンのデータを読み取ります。
        MaxVersion: 1,
        // ローカル トランザクション ID を指定します。
        TransactionId: transId,
    }
    getRowRequest := &tablestore.GetRowRequest{
        SingleRowQueryCriteria: criteria,
    }
    getResp, err := client.GetRow(getRowRequest)
    if err != nil {
        fmt.Println("getrow はエラーで失敗しました:", err)
    } else {
        fmt.Println("get row col0 の結果は ", getResp.Columns[0].ColumnName, getResp.Columns[0].Value)
    }

    // ローカル トランザクションをコミットまたは破棄します。ローカル トランザクションのコミットと破棄は、読み取り操作に同じ効果があります。
    // ローカル トランザクションをコミットして、ローカル トランザクション内のすべてのデータ変更を有効にします。
    request := &tablestore.CommitTransactionRequest{
        TransactionId: transId,
    }
    commitResponse, err := client.CommitTransaction(request)
    if err != nil {
        fmt.Println("トランザクションのコミットはエラーで失敗しました:", err)
    } else {
        fmt.Println("トランザクションのコミットが完了しました。RequestId は", commitResponse.RequestId)
    }
    // ローカル トランザクションを破棄します。この場合、ローカル トランザクション内のすべてのデータ変更は、データテーブル内のデータに適用されません。
    //request := &tablestore.AbortTransactionRequest{
    //    TransactionId: transId,
    //}
    //abortResponse, err := client.AbortTransaction(request)
    //if err != nil {
    //    fmt.Println("トランザクションの中止はエラーで失敗しました:", err)
    //} else {
    //    fmt.Println("トランザクションの中止が完了しました。RequestId は", abortResponse.RequestId)
    //}
}

参照

複数のデータ行を同時に書き込む場合、または主キー値が特定の範囲内にあるデータを読み取る場合は、ローカル トランザクションを作成します。次に、データの書き込みまたはデータの読み取りトピックに記載されているサンプルコードを参照して、ローカル トランザクション ID を含むリクエストを開始します。