Locking in Systems: Minimizing Contention for a Smoother Ride

Locking in Systems: Minimizing Contention for a Smoother Ride

When we talk about locking in databases, it’s like controlling access to specific data to ensure that everything stays consistent. But just like managing a crowd at a busy event, improper handling can lead to bottlenecks and delays. Imagine a fintech app where users frequently check balances, transfer funds, and view transaction histories. If we’re not careful with how we lock the database, this can lead to queues, slowdowns, and an overall poor experience.

Let’s explore how we can minimize these lock-related contentions using some practical strategies with sample database tables.

1. Reduce the Duration of Locks: Get in, Get Out Quickly

The key to minimizing contention is reducing how long a lock is held. The faster we can perform an operation and release the lock, the smoother the system will run.

A. Move Code Out of Synchronization

Consider a fintech application with three database tables:

  1. User Table (users): Stores user authentication details.
  2. Balance Table (balances): Keeps track of each user’s current balance.
  3. Transaction Table (transactions): Logs every transaction the user performs.

In this setup, the users table handles authentication and other non-financial user information, such as email addresses or profile details. This table doesn’t need to lock the balances table when verifying a user’s login credentials. By moving this non-financial data out of the synchronization process, we avoid unnecessary locks, allowing multiple users to log in simultaneously without waiting.


A diagram showing three separate tables with arrows indicating that the users table handles authentication, while balances and transactions focus on financial data.
A diagram showing three separate tables with arrows indicating that the


B. Lock Stripping / Lock Splitting

Let’s say our app supports different types of financial operations, like checking the balance and transferring funds. Instead of locking the entire balances table every time a user performs any operation, we can split the locks. When a user checks their balance, we only lock the specific row in the balances table for that user. Meanwhile, transactions like fund transfers lock both the balances and transactions tables but only for the affected rows.

For example:

  • balances table: Locks only the row corresponding to the user’s account when updating the balance.
  • transactions table: Logs the transaction without affecting the entire balance.

This method, known as lock splitting, ensures that different operations don’t block each other unnecessarily.


a locked row in the


2. Replace Exclusive Locks with Coordination Mechanisms: Sharing is Caring

Sometimes, it’s not just about how long a lock is held but how you coordinate access to shared resources.

A. Read-Write Locks: A Balanced Approach

Imagine that multiple users want to check their balances simultaneously. Instead of locking the entire balances table, we can use a Read-Write Lock. This allows multiple users to read their balances at the same time, while only one user can update a balance at any given moment.

For example, the system lets all users read their balance from the balances table simultaneously. But when a user initiates a fund transfer, the system locks only the relevant row in the balances table, allowing the update to happen without affecting other users.

B. Atomic Variables: The Magic Pen

Let’s say we’re updating a counter for the number of transactions a user has performed. Instead of locking the entire transactions table, we use atomic variables. It’s like having a special pen that lets one user update the counter while others can still read it. This reduces the need for traditional locks and keeps the app responsive.


Multiple users can read the counter but only one can write to it using a special pen

Two Ways of Locking Shared Resources: Which Path to Choose?

When dealing with databases, there are two main approaches to locking: Pessimistic and Optimistic. Your choice depends on the specific needs of your application.

A. Pessimistic Locking: The Traditional Approach

Pessimistic locking is like reserving a table at a restaurant before you arrive. In our fintech app, this would mean locking the user’s balance row in the balances table before starting any transaction process. The lock stays in place until the transaction is complete.

Pros:

  • Consistency: Prevents concurrent modifications, ensuring data integrity.
  • Explicit Control: Developers know exactly when and where locks are applied.
  • Avoids Race Conditions: By locking, you prevent multiple transactions from clashing.

Cons:

  • Blocking Potential: Other users may have to wait if one user locks the resource.
  • Performance Impact: Can slow down the system under heavy load.
  • Deadlocks: The risk increases in complex transactions.

B. Optimistic Locking: A More Flexible Approach

Optimistic locking takes a more relaxed approach. The idea is to proceed with operations without locking initially, only checking for conflicts at the end. In our fintech app, this means updating the balance and only locking it when necessary.

For example:

  1. Retrieve the user’s balance from the balances table.
  2. Perform the transaction (e.g., deduct funds).
  3. Before committing the transaction, check if the balance has changed. If not, commit the changes; if it has, retry.

Pros:

  • Reduced Lock Time: Locks are held only when absolutely necessary.
  • Increased Concurrency: Multiple operations can proceed in parallel, improving performance.

Cons:

  • Risk of Retrying: Frequent updates can lead to multiple retries, which may degrade performance.
  • Suitable for Low Contention: Best when the likelihood of conflicts is low.


Flowchart showing optimistic locking
A flowchart showing the steps in optimistic locking, highlighting the lock being applied only at the final stage.


要查看或添加评论,请登录

Joel Ndoh的更多文章

社区洞察

其他会员也浏览了