Published on

Dirty Reads

Authors
  • avatar
    Name
    Zain Hasan
    Twitter

Introduction

Most database literature discusses the ACID foundations - Atomicity, Consistency, Isolation, and Durability. As we explore each of these concepts in more detail, we discover that implementing them involves trade-offs and potential pitfalls. Database engineers must navigate a range of choices to optimize their databases for the desired behavior. Determining the desired behavior of a database requires careful consideration, as it can vary depending on the philosophy and raison d'être of the database. A choice made for a Postgres will be very different from the one made for a database like Cassandra.

Isolation

Database isolation is a way to ensure that when multiple users or applications are accessing the same database simultaneously, their transactions are kept separate and do not interfere with each other. It's like having individual rooms for each person in a hotel, so they can have privacy and not disturb others while they're staying there. This helps to maintain data consistency and accuracy, and prevent errors or conflicts that might occur if everyone was accessing the same data at the same time without any boundaries. If not dealt with appropriately, simultaneous transactions accessing the same data can lead to race conditions. This can lead to a lot of problems.

Read Phenomena

Achieving isolation can be difficult due to various read phenomena that can occur in databases. I will cover briefly what a Dirty Read is:

Dirty Reads

A transaction reads uncommitted data written by another transaction. For example, we have two transactions T1 and T2 trying to read and update x concurrently.

x := 0

t1 := NewTransaction("T1", func() {
    x += 1
})

t2 := NewTransaction("T2", func() {
    x += 2
})

go t1.exec()
go t2.exec()

fmt.Printf("The value of x is : %d", x)

These two transactions are involved in a race condition to update x. The final value of x is unpredictable.