Skip to content

Optimistic Concurrency

Steve Ives edited this page Mar 30, 2020 · 13 revisions

Harmony Core Logo

Optimistic Concurrency

Optimistic concurrency is an alternative to locking and holding locks on records for the duration of a transaction, only releasing the lock when you've written the updated contents of a record. Instead of locking optimistic concurrency uses a concurrency token that is created or retrieved after a record is read. When you're ready to update the record, using the concurrency token, check that the record hasn't changed since you read it. If the record hasn't changed, then it is written. If the record has been changed there are a few options for conflict resolution. It is possible to merge the record using hand written code, or you can just abort the transaction and try again.

Why Not Locks

Locks have been used in business critical applications for as long as businesses have been writing software. They are straightforward to think about and other than dead locks they tend to be trouble free. Unfortunately they are exclusive and mean there is a single point of bottleneck for a contested record. Even if a record is not contested, taking a lock requires more I/O operations. All of this adds up to reduce your applications ability to scale up to servers with more CPU cores or more RAM. Operating over the network this effect is made worse because the that latency of a round trip to the server.

How

Synergy DBMS is capable of returning Global RFA's for records that are read from ISAM files. Global RFA's or GRFA's are usable as a Concurrency Token. Additionally GRFA's are used where available as the ETag for any data object returned from an OData endpoint. This lets a client of our web service to request data and then make an update to a field, passing the ETag they received from the original request. Using that concurrency token, we validate that the record hasn't changed since it was read, then update it if it hasn't. If it has changed an event will be fired that allows your application to run custom code to merge the record changes into the current record or to just fail the transaction if that isn't possible.

File I/O

The FileIO classes enable optimistic concurrency using the following routines on DataObjectIOBase

  • UpdateRecordUsingGRFA
  • DeleteRecordUsingGRFA

If the GRFA for the target record has not changed it will be updated/deleted accordingly. If the record has changed then the options available depend on what classes are being used. You can intercept the "Record Not Same" error by inheriting from DataObjectIOBase or IsamDataObjectIO and then overriding the method OnRecordNotSame.

EF Core Provider

By default all operations in EF Core are done using an optimistic concurrency model. The underlying framework tracks all data objects returned from EF Core. If changes are made to a data object or if Add or Delete are called on a DBSet those changes will not be reflected on disk until a call to SaveChanges is made on the DBContext. Once the provider starts saving changes is will operate in two phases, first it will attempt to acquire locks for all of the records that have been changed or deleted. Then It will perform any record insertions, followed by writing the changed records and finishing up with deletions. In this way we can ensure that baring physical IO failures, transactions will either commit fully or not at all. Currently there is a small window for abnormal behavior if multiple records with the same primary key are inserted simultaneously or if a record is updated to an invalid key.

Clone this wiki locally