Both optimistic and pessimistic locking are mechanisms to ensure data integrity when multiple transactions are trying to access or modify the same data concurrently. They differ in how they handle potential conflicts.
1. Optimistic Locking
Assumption: The optimistic approach assumes that conflicts (i.e., multiple transactions trying to modify the same data at the same time) are rare. Instead of locking data during a transaction, it allows transactions to proceed without locking and detects conflicts when changes are being committed.
How It Works:
The data being updated includes a version number or timestamp field.
When a transaction reads the data, it also reads the version number.
When the transaction attempts to update the data, it checks if the version number has changed since the data was first read.
If the version number is unchanged, the update proceeds, and the version number is incremented.
If the version number has changed (indicating another transaction modified the data), the update is rejected, and the transaction can retry or fail gracefully.
Use Case:
Best suited for scenarios where conflicts are infrequent and locking data upfront is expensive.
Example: In e-commerce, where multiple users may view and attempt to purchase a product, optimistic locking can help avoid unnecessary locking of the product while still ensuring that conflicting changes are detected.
Example:
Let’s say we are using a version column to track changes:
// Assume an optimistic locking strategy in a Sequelize model await GameSettingModel.update( { is_active: true }, { where: { id: 42, version: currentVersion }, // check current version } );
If the version is not the same as when the row was read, the transaction fails, indicating a conflict occurred.
Pros:
No need to lock data during the read, allowing for more concurrency.
Avoids unnecessary blocking of rows unless there’s an actual conflict.
Cons:
A failed update can require retry logic, leading to potentially more complex code to handle retries.
2. Pessimistic Locking
Assumption: The pessimistic approach assumes that conflicts are likely, so it locks data immediately when it is being read or updated to prevent any other transactions from modifying it until the lock is released.
How It Works:
A transaction reads data with a lock (e.g., FOR UPDATE).
The lock prevents other transactions from modifying the data until the transaction holding the lock is finished (committed or rolled back).
This ensures that once the transaction starts, no other transaction can modify the same data, avoiding conflicts upfront.
Use Case:
Best suited for scenarios where conflicts are likely or where data integrity is critical, and you want to avoid complex conflict resolution later.
Example: In a financial system, where multiple transactions might try to withdraw from the same account, pessimistic locking ensures that only one transaction can proceed at a time, avoiding overdrafts or other issues.
Example:
Using Sequelize’s FOR UPDATE lock for pessimistic locking: