Após ativar o recurso de transação local em uma tabela de dados, crie uma transação local com base em um valor de chave de partição específico para executar operações de leitura e gravação nos dados dessa transação. Esse recurso permite realizar operações atômicas de leitura e gravação em uma ou mais linhas.
Pré-requisitos
Cliente inicializado. Para mais informações, consulte Inicializar um cliente do Tablestore.
-
Tabela de dados criada com o recurso de transação local ativado.
NotaSe você não ativou o recurso de transação local ao criar a tabela de dados e deseja utilizar esse recurso posteriormente, envie um ticket.
Observações de uso
Os recursos de coluna de chave primária com incremento automático e de transação local não podem ser usados simultaneamente.
O bloqueio pessimista controla as operações simultâneas em uma transação local.
-
A validade máxima de uma transação local é de 60 segundos.
Caso a transação local não seja confirmada (committed) ou abortada dentro desse prazo, o servidor do Tablestore considera que houve timeout e encerra a transação.
Uma transação pode ser criada no servidor do Tablestore mesmo que um erro de timeout seja retornado. Nessa situação, reenvie a solicitação de criação após o timeout da transação criada anteriormente.
Transações locais não confirmadas podem se tornar inválidas. Se isso ocorrer, tente novamente as operações dessa transação.
Sem operações de gravação nos dados de uma transação local, as ações de confirmar e abortar produzem o mesmo efeito.
-
O Tablestore impõe os seguintes limites às operações de leitura e gravação em dados de uma transação local:
O ID da transação local não permite acessar dados fora do intervalo definido pelo valor da chave de partição usado na criação da transação.
Todas as solicitações de gravação na mesma transação devem ter valores de chave de partição idênticos ao valor usado para criar a transação. Essa restrição não se aplica a solicitações de leitura.
Apenas uma solicitação por vez pode utilizar uma transação local. Enquanto ela estiver em uso, outras operações com o mesmo ID de transação local falharão.
-
O intervalo máximo entre duas operações consecutivas de leitura ou gravação nos dados de uma transação local é de 60 segundos.
Se nenhuma operação de leitura ou gravação for realizada nos dados da transação local por mais de 60 segundos, o servidor do Tablestore considerará que houve timeout e abortará a transação.
Cada transação aceita até 4 MB de dados gravados. O cálculo do volume de dados segue o mesmo método de uma solicitação de gravação comum.
Se nenhum número de versão for especificado para uma célula, o servidor do Tablestore atribuirá automaticamente um número de versão no momento da gravação na transação, e não quando a transação for confirmada.
Quando uma solicitação BatchWriteRow inclui um ID de transação local, todas as linhas dessa solicitação só podem ser gravadas na tabela correspondente a esse ID.
Ao usar uma transação local, um bloqueio de gravação é aplicado aos dados do valor da chave de partição associado à transação. Somente solicitações de gravação contendo o ID da transação local e destinadas a modificar dados dentro dela terão sucesso. Outras solicitações não transacionais ou com IDs de transações diferentes falharão. Os dados são desbloqueados quando a transação é confirmada, abortada ou expira.
A transação local permanece válida mesmo se uma solicitação de leitura ou gravação com seu ID for rejeitada. Defina uma regra de nova tentativa para reenviar a solicitação ou aborte a transação.
Como verificar se as transações locais estão ativadas para uma tabela de dados?
O console do Tablestore não exibe o status de transação local de uma tabela de dados. O comando CLI desc exporta o esquema da tabela, mas não inclui o atributo de transação local.
Para confirmar se as transações locais estão ativadas em uma tabela de dados, utilize um SDK para chamar a operação DescribeTable. A resposta contém os metadados completos da tabela, incluindo o status da transação local.
Caso não tenha acesso à operação DescribeTable, verifique se setLocalTxnEnabled(true) foi chamado no código usado para criar a tabela de dados ou envie um ticket para confirmar se esse recurso foi ativado anteriormente.
Parâmetros
|
Parâmetro |
Obrigatório |
Descrição |
|
TableName |
Sim |
Nome da tabela de dados. |
|
PrimaryKey |
Sim |
Chave primária da tabela de dados.
|
|
TransactionId |
Sim |
ID que identifica exclusivamente uma transação local. Especifique um ID de transação local ao ler e gravar dados em uma transação local. |
Exemplos
Usar o recurso de transação local para gravar uma linha de dados
O código de exemplo a seguir demonstra como criar uma transação local com base em um valor de chave de partição especificado em uma tabela e gravar uma linha de dados nessa transação. Se a gravação for bem-sucedida, confirme a transação. Caso contrário, descarte-a.
func transactionPutRow(client *tablestore.TableStoreClient, tableName string) {
// Specify a partition key value for the local transaction. The partition key is the first primary key column.
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("failed to create transaction", err)
return
}
// Obtain the local transaction 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)
// Specify the local transaction ID, which can be obtained by using StartLocalTransactionResponse.TransactionId.
putRowChange.TransactionId = transId
putRowRequest := &tablestore.PutRowRequest{
PutRowChange: putRowChange,
}
_, err = client.PutRow(putRowRequest)
if err != nil {
// If a row of data fails to be written in the local transaction, discard the local transaction. In this case, all data modifications in the local transaction do not apply to the data in the data table.
fmt.Println("putrow failed with error:", err)
request := &tablestore.AbortTransactionRequest{
TransactionId: transId,
}
abortResponse, err := client.AbortTransaction(request)
if err != nil {
fmt.Println("abort transaction failed with error:", err)
} else {
fmt.Println("abort transaction finished. RequestId is", abortResponse.RequestId)
}
} else {
// If a row of data is written in the local transaction, commit the local transaction. In this case, all data modifications in the local transaction take effect. You can discard a local transaction to invalidate all data modifications in the local transaction.
fmt.Println("putrow finished")
request := &tablestore.CommitTransactionRequest{
TransactionId: transId,
}
commitResponse, err := client.CommitTransaction(request)
if err != nil {
fmt.Println("commit transaction failed with error:", err)
} else {
fmt.Println("commit transaction finished. RequestId is", commitResponse.RequestId)
}
}
}
Usar o recurso de transação local para ler uma linha de dados
O código de exemplo a seguir demonstra como criar uma transação local com base em um valor de chave de partição especificado em uma tabela e ler uma linha de dados nessa transação:
func transactionGetRow(client *tablestore.TableStoreClient, tableName string) {
// Specify a partition key value for the local transaction. The partition key is the first primary key column.
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("failed to create transaction", err)
return
}
// Obtain the local transaction ID.
transId := response.TransactionId
// Read data.
getRowPk := new(tablestore.PrimaryKey)
getRowPk.AddPrimaryKeyColumn("pk1", "pk1value")
getRowPk.AddPrimaryKeyColumn("pk2", int64(18))
criteria := &tablestore.SingleRowQueryCriteria{
PrimaryKey: getRowPk,
TableName: tableName,
// Read the latest version of data.
MaxVersion: 1,
// Specify the local transaction ID.
TransactionId: transId,
}
getRowRequest := &tablestore.GetRowRequest{
SingleRowQueryCriteria: criteria,
}
getResp, err := client.GetRow(getRowRequest)
if err != nil {
fmt.Println("getrow failed with error:", err)
} else {
fmt.Println("get row col0 result is ", getResp.Columns[0].ColumnName, getResp.Columns[0].Value)
}
// Commit or discard the local transaction. Committing and discarding a local transaction have the same effect on a read operation.
// Commit the local transaction to allow all data modifications in the local transaction to take effect.
request := &tablestore.CommitTransactionRequest{
TransactionId: transId,
}
commitResponse, err := client.CommitTransaction(request)
if err != nil {
fmt.Println("commit transaction failed with error:", err)
} else {
fmt.Println("commit transaction finished. RequestId is", commitResponse.RequestId)
}
// Discard the local transaction. In this case, all data modifications in the local transaction do not apply to the data in the data table.
//request := &tablestore.AbortTransactionRequest{
// TransactionId: transId,
//}
//abortResponse, err := client.AbortTransaction(request)
//if err != nil {
// fmt.Println("abort transaction failed with error:", err)
//} else {
// fmt.Println("abort transaction finished. RequestId is", abortResponse.RequestId)
//}
}
Referências
Para gravar várias linhas de dados simultaneamente ou ler dados cujos valores de chave primária estejam dentro de um intervalo específico, crie uma transação local. Em seguida, consulte o código de exemplo fornecido no tópico Gravar dados ou Ler dados para iniciar uma solicitação que inclua o ID da transação local.