What Does Btrieve Error 080 Mean?

Release Date: 07/16/2020
Version: 7.x & up

Q - I received the following error in Elliott Business Software:
      Btrieve Error 080 on Order Header File
I looked up the KB article: http://support.elliott.com/knowledgebase/articles/834963-btrieve-error-codes-001-199 and according to its explanation, Btrieve Error 080 means the following:

080: The MicroKernel encountered a record-level conflict

The MicroKernel did not perform the Update or Delete operation because of a record-level conflict. For example, station A reads a record, station B reads the same record and updates it, and then station A attempts to update the record. The application should reread the record prior to resending an Update or Delete operation. Alternatively, the application can employ record locks to avoid conflicts.

In key-only files, you receive this status code if the record is moved in the file b-tree after being read and before being updated or deleted. A record can move as a result of other records being inserted, updated, or deleted.

What does it really mean?

AHere is my explanation of how error 080 can happen: First, let's say user A reads record 1 at 9:00:00. Then user B reads the same record 1 at 9:00:01. User A proceeds to change record 1 at 9:00:02, then when user B proceeds to change the same record 1 at 9:00:03, the  PSQL database engine knows that in between user B reading and trying to update record 1, it has been changed already. The update will override user’s A change, which is not acceptable, and thus the system gives user B the error 9/080. 

One way to handle the above scenario in programming is to use the "lock" feature. Using the lock feature, when user A reads record 1 at 9:00:00, the system should also “lock” it. When user B reads record 1 at 9:00:01 with the lock, it will be rejected so it would never proceed to the stage of updating at 9:00:03. Of course the complicated question is how does user B handle the scenario when it is rejected when the record is read with the lock. Sometimes there’s a user interface to handle this, and sometimes there’s not. When there’s no user interface, we can wait in the loop until the lock is released, but that would mean user B is “locked” in a loop until user A releases the record. What if user A decides to take a lunch break before coming back to release the lock? Also, there’s no guarantee that user A intends to update record 1 later on at all, so to lock that record for a period (possibly an extensive period) of time to guarantee the safety of an update can be wasteful and does not promote good concurrency for a big team working together on the same database. So there’s a trade-off with using the lock feature. 

There’s another way to handle the above scenario gracefully. We call it “phantom locking.” But the programming tends to be a lot more complicated. So far we have applied “phantom locking” logic to Elliott 8.5 & later for Customer and Item File maintenance. For the remaining areas, the codes are usually written in a more straightforward way. In many situations, we tend to favor “sharing” (no locking) over “locking," which may result in the possibility of receiving error 9/080. Fortunately, there is no database integrity issue because in the above scenario PSQL prevents user B from updating, thus avoiding the integrity issue.


Feedback and Knowledge Base