Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why write skew can happen in Repeatable reads?

Wiki says;

Repeatable read:
In this isolation level, a lock-based concurrency control DBMS implementation keeps read and write locks (acquired on selected data) until the end of the transaction. However, range-locks are not managed, so phantom reads can occur.

Write skew is possible at this isolation level, a phenomenon where two writes are allowed to the same column(s) in a table by two different writers (who have previously read the columns they are updating), resulting in the column having data that is a mix of the two transactions.

I'm curious about why write skew can happen in Repeatable reads? It says that it will keep read and write locks until the end of the transaction and the write skew happens when previously read the columns they are updating, so how can lock a write lock when a read lock is locked?

like image 479
handora Avatar asked Jan 24 '18 08:01

handora


People also ask

How do you stop writing skew?

Potential inconsistency problems arising from write skew anomalies can be fixed by adding (otherwise unnecessary) updates to the transactions in order to enforce the serializability property. Add a special conflict table, which both transactions update in order to create a direct write–write conflict.

What is read skew?

Read skew can occur when there are integrity constraints between two or more data items.

What does repeatable read mean?

Repeatable read is a higher isolation level, that in addition to the guarantees of the read committed level, it also guarantees that any data read cannot change, if the transaction reads the same data again, it will find the previously read data in place, unchanged, and available to read.

How to prevent write skews when using repeatable read and serializable?

SQL Server default locking-based isolation levels can prevent write skews when using Repeatable Read and Serializable. Neither one of its MVCC-based isolation levels ( MVCC -based) can prevent/detect it instead.

What is a write skew?

Obviously, one of these two transactions needs to fail to preserve the serializable transaction schedule. This anomaly is called a Write Skew, and we are going to see how this phenomenon is handled by various RDBMS.

What is the difference between READ COMMITTED and REPEATABLE READ?

With transaction 1 as READ COMMITTED, you can update a row in transaction 2 after you selected it in transaction 1. With transaction 1 as REPEATABLE READ, you cannot update a row in transaction 2 after you selected it in transaction 1.

How does Alice handle read skew?

Alice thread is resumed and she selects the PostDetails record. If read skew is permitted, Alice sees Bob’s update and she can assume that the previous Post version (that she read at the beginning of her transaction) was issued by Bob, therefore breaking consistency.


1 Answers

Repeatable read isolation level guarantees that each transaction will read from the consistent snapshot of the database. In other words, a row is retrieved twice within the same transaction always has the same values.

Many databases such as Postgres, SQLServer in repeatable read isolation levels can detect lost update (a special case of write skew) but others don't. (i.e: InnoDB engine in MySQL)

We're back to write skew phenomena problem. There are situations that most database engines cannot detect in the repeatable read isolation. One case is when 2 concurrent transactions modifies 2 different objects and making race conditions.

I take an example from the book Designing Data-Intensive Application. Here is the scenario:

You are writing an application for doctors to manage their on-call shifts at a hospital. The hospital usually tries to have several doctors on call at any one time, but it absolutely must have at least one doctor on call. Doctors can give up their shifts (e.g., if they are sick themselves), provided that at least one colleague remains on call in that shift

The next interesting question is how we can implement this under databases. Here is pseudocode SQL code:

BEGIN TRANSACTION;
    SELECT * FROM doctors
        WHERE on_call = true
        AND shift_id = 1234;
    if (current_on_call >= 2) {
        UPDATE doctors
        SET on_call = false WHERE name = 'Alice' AND shift_id = 1234;
    }
COMMIT;  

Here is the illustration: Flow Data

As the above illustration, we see that Bob and Alice run above SQL code concurrently. However Bob and Alice modify different data, Bob modified Bob's record and Alice modified Alice's record. Databases at repeatable-read isolation level no way can know and check the condition (total doctor >= 2) has been violated. Write skew phenomena has happened.

To solve this problem, there are 2 methods proposed:

  1. locks all records that are being called manually. So either Bob or Alice will wait until other finishes transaction.

Here is some pseudocode using SELECT .. FOR UPDATE query.

BEGIN TRANSACTION;
    SELECT * FROM doctors
        WHERE on_call = true
        AND shift_id = 1234 FOR UPDATE; // important here: locks all records that satisfied requirements.

    if (current_on_call >= 2) {
        UPDATE doctors
        SET on_call = false WHERE name = 'Alice' AND shift_id = 1234;
    }
  COMMIT;  
  1. Using a more strict isolation level. Both MySQL, Postgres T-SQL provides serialize isolation level.
like image 131
hqt Avatar answered Nov 02 '22 00:11

hqt