awslabs / dynamodb-transactions

Apache License 2.0
356 stars 90 forks source link

Transaction Record Data showing up in Main record Table #38

Closed draukadin closed 6 years ago

draukadin commented 6 years ago

In MyTable I some times get records that have my hash key with the following fields _TxD, _TxId, and _TxT and none of my fields aside from the hash key.

In the Transactions Table I can take the _TxId value from MyTable and look up a record there that has these fields _TxId, _TxD, _TxR, _TxS, and _TxV

The TxD field on MyTable and in the Transaction Table do not have the same value (about 7 seconds difference) and the values of the other fields are provided below except _TxR

MyTable

  1. _TxD value: 1505692898.128
  2. _TxT value: 1

Transactions Table

  1. _TxD value: 1505692981.343
  2. _TxS value: R
  3. _TxV value: 3
  4. _TxR value: I suspect this to be an encrypted String that is all my requests involved in the transaction.

In what valid use cases would these transaction attribute values be written to MyTable instead of the data in the request involved in the transaction? Is there a way I can detect when the transaction library does this if it is a valid use case? If it is a valid use case what recovery steps should I take to re-process the transaction so my data is persisted into MyTable?

Yanacek commented 6 years ago

The "_TxT = 1" indicates that the item was inserted into the table so that a lock could be taken. If you start a transaction that involves an item that doesn't exist, the library needs to insert a temporary "hidden" item in order to take a lock on it. The lock needs to be there so that the library detects if there are multiple colliding transactions operating on the same item at once. Some javadocs about this are here: https://github.com/awslabs/dynamodb-transactions/blob/master/src/main/java/com/amazonaws/services/dynamodbv2/transactions/Transaction.java#L80

"_TxS = R" means that the transaction was rolled back. The fact that the timestamp on the transient item in MyTable was so much later suggests that the application performing the write in the first place did not realize that the transaction was rolled back, and then went and performed the transient item insert in the table. Fortunately, it's easy to clean up these records. Call TransactionManager.resume() with the corresponding transaction id, and then call the sweep() method on the Transaction: https://github.com/awslabs/dynamodb-transactions/blob/master/src/main/java/com/amazonaws/services/dynamodbv2/transactions/Transaction.java#L349 . It will see that the transaction was rolled back, and make sure that any of these "transient" items are removed.

As an aside, "_TxR" is just base64 encoded, not encrypted. You can read that to see the internal state of the requests in the transaction, if you are curious.