Introduction

In real-world applications, multiple users or services often try to read or update the same database row or table simultaneously.

This topic is frequently asked in .NET interviews and is crucial for building reliable and consistent applications. In this article, we explain concurrency concepts in plain terms and illustrate them with a ticket-booking scenario.

Understanding Concurrency in Databases

Concurrency happens when multiple processes access the same data simultaneously. Without proper handling, this can lead to race conditions and lost updates. Databases handle concurrency using transactions, locks, and versioning mechanisms.

Here is a simple breakdown of the two main approaches databases use to handle simultaneous updates.

1. Pessimistic Concurrency (The "Locking" Method)

This approach is protective. It assumes that if two people are looking at the same data, they will inevitably clash, so it takes precautions early.

2. Optimistic Concurrency (The "Versioning" Method)

This approach is flexible. It assumes that most of the time, people won't try to change the exact same thing at the exact same second.

Beginner-Friendly Ticket Booking Example

Imagine a movie theater with only one seat left: Seat 10.

Without concurrency control:

With proper concurrency handling:

  1. Pessimistic Concurrency (Locking):

    • Alice’s transaction locks Seat 10.

    • Bob’s transaction waits until the lock is released.

    • Alice books successfully → Bob sees seat is taken.

  2. Optimistic Concurrency (Versioning):

    • Both Alice and Bob read Seat 10 simultaneously → available.

    • Alice books first → database updates the row with a version number.

    • Bob tries to book → version mismatch detected → booking fails.

Result: Only one person successfully books the seat. This prevents double booking and ensures data integrity.

Conclusion

Concurrency is a fundamental concept in database-driven applications. In this article we have seen how understanding how concurrency works is essential for building robust .NET applications.