使用局部事務功能,建立資料範圍在一個分區索引值內的局部事務。對局部事務中的資料進行讀寫操作後,可以根據實際提交或者丟棄局部事務。局部事務通過悲觀鎖(Pessimistic Lock)實現並發控制。

目前局部事務功能處於邀測中,預設關閉。如果需要使用該功能,請提交工單進行申請。

使用局部事務可以指定某個分區索引值內的操作是原子的,對分區索引值內的資料進行的操作要麼全部成功要麼全部失敗,並且所提供的隔離等級為讀已提交。

前提條件

  • 已初始化Client,詳情請參見初始化
  • 已建立資料表並寫入資料。

使用方法

  1. 使用startLocalTransaction在指定的分區索引值建立一個局部事務,並擷取局部事務ID。
  2. 對局部事務範圍內的資料進行讀寫操作。

    支援對局部事務進行操作的介面為GetRow、PutRow、DeleteRow、UpdateRow、BatchWriteRow和GetRange。

  3. 使用commitTransaction提交局部事務或者使用abortTransaction丟棄局部事務。

限制

  • 每個局部事務從建立開始生命週期最長為60秒。

    如果超過60秒未提交或丟棄局部事務,Tablestore服務端會認為此局部事務逾時,並將局部事務丟棄。

  • 如果建立局部事務時逾時,此請求可能在Tablestore服務端已執行成功,此時使用者需要等待該局部事務逾時後重新建立。
  • 未提交的局部事務可能失效,如果出現此情況,需要重試該局部事務內的操作。
  • 在局部事務中讀寫資料有如下限制:
    • 不能使用局部事務ID訪問局部事務範圍(即建立時使用的分區索引值)以外的資料。
    • 同一個局部事務中所有寫請求的分區索引值必須與建立局部事務時的分區索引值相同,讀請求則無此限制。
    • 一個局部事務同時只能用於一個請求中,在使用局部事務期間,其它使用此局部事務ID的操作均會失敗。
    • 每個局部事務中兩次讀寫操作的最大間隔為60秒。

      如果超過60秒未操作局部事務,Tablestore服務端會認為此局部事務逾時,並將局部事務丟棄。

    • 每個局部事務中寫入的資料量最大為4 MB,按正常的寫請求資料量計算規則累加。
    • 如果在局部事務中寫入了未指定版本號碼的Cell,該Cell的版本號碼會在寫入時(而非提交時)由Tablestore服務端自動產生,建置規則與正常寫入一個未指定版本號碼的Cell相同。
    • 如果BatchWriteRow請求中帶有局部事務ID,則此請求中所有行只能操作該局部事務ID對應的表。
    • 在使用局部事務期間,對應分區索引值的資料會被上寫鎖,只有持有局部事務ID在局部事務範圍內的寫請求才會成功。其它非事務請求或持有其他局部事務ID在局部事務範圍內的寫請求均會失敗。在局部事務提交、丟棄或逾時後,對應的鎖也會被釋放。
    • 帶有局部事務ID的讀寫請求失敗不會影響局部事務本身的存活情況,您可以指定重試規則進行重試或者主動丟棄當前局部事務。

參數

參數 說明
tableName 資料表名稱。
primaryKey 資料表主鍵。
  • 建立局部事務時,只需要指定局部事務對應的分區索引值。
  • 建立局部事務後,對局部事務範圍內的資料進行讀寫操作時,需要指定完整主鍵。
transactionId 局部事務ID,用於唯一標識一個局部事務。

建立局部事務後,操作局部事務時均需要帶上局部事務ID。

樣本

  • 提交局部事務,使所有資料修改生效。
    (async () => {
        try {
    
            //建立局部事務。
            const response = await client.startLocalTransaction({
                tableName,
                primaryKey: [{  //只需要指定局部事務對應的分區索引值。
                    "id": "partitionKeyValue"
                }]
            });
    
            //擷取局部事務ID。
            const transactionId = response.transactionId;
    
            //對局部事務範圍內的資料進行寫操作。
            await client.putRow({
                tableName,
                condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, null),
                primaryKey,
                attributeColumns: [{
                    col: 'updated'
                }],
                transactionId
            });
    
            //提交局部事務。
            await client.commitTransaction({
                transactionId
            })
        } catch (e) {
            console.error(e)
        }
    })();
  • 丟棄局部事務,放棄所有資料修改。
    (async () => {
        try {
    
            //建立局部事務。
            const response = await client.startLocalTransaction({
                tableName,
                primaryKey: [{  //只需要指定局部事務對應的分區索引值。
                    "id": "partitionKeyValue"
                }]
            });
            //擷取局部事務ID。
            const transactionId = response.transactionId
    
            //對局部事務範圍內的資料進行寫操作。
            await client.putRow({
                tableName,
                condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, null),
                primaryKey,
                attributeColumns: [{
                    col: 'updated'
                }],
                transactionId
            });
            //丟棄局部事務。
            await client.abortTransaction({
                transactionId
        })
      } catch (e) {
        console.error(e)
      }
    })();