Fix MySQL isolation level for read-modify-write ops #2150
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Certain operations in SPIRE are read-modify-write, i.e., they read rows, process columns on those rows, and then update the rows as part of a single transaction. This is for sensitive operations like bundle appending/pruning.
We've relied on the REPEATABLE READ isolation level to provide us the consistency guarantees we need over these kind of operations operation, namely that which prevents concurrent transactions from updating the same target row(s). This is to prevent one transaction from undoing the action just performed by another. For example, if two servers attempt to append key material to the bundle concurrently, we don't want the append op from one to accidentally "undo" the append of the other, as they are both updating the same bundle row.
We chose REPEATABLE READ based on an assumption that PostgreSQL behavior was universal.
Unfortunately MySQL REPEATABLE READ is weaker than that of PostgreSQL. While, PostgreSQL fails concurrent transactions that try to update the same target row, MySQL does not. For MySQL, we need SERIALIZABLE, which is the same as REPEATABLE READ except that it converts
SELECT
toSELECT ... LOCK FOR SHARE MODE
which "sets a shared lock that permits other transactions to read the examined rows but not to update or delete them", which gives us the result we need.Fixes: #2149