Examples of Multiple Concurrency Control
The following examples illustrate the use of the different concurrency control mechanisms.
Example 1
Example 1 shows the interaction between explicit and implicit record locks, implicit page locks, and passive concurrency. Assume that the two records manipulated in this example (record A and record B) reside on the same data page and that the file has only one key. For further explanation of each step, see the paragraphs following the example.
The following table shows the interactions among implicit and explicit record locks, implicit page locks, and passive concurrency.
1. Begin Concurrent Transaction with multiple no-wait lock bias (1419)
2. Begin Concurrent Transaction with single wait lock bias (1119)
3. Read Record A using Get Equal with single no-wait lock bias (205)
4. Read record B using Get Equal (5) (single wait lock bias inherited)
5. Read record B using Get Equal (5)
6. Attempt to Delete (4) record B: MicroKernel returns Status Code 84, and client 3 must retry
7. Update (3) record B
8. Attempt to Update (3) record A: MicroKernel must retry
9. End Transaction (20)
10. Retry Update (3) of record A: Successful
11. Retry Delete (4) of record B: MicroKernel returns Status Code 80, and client 3 must reread record B
12. Reread record B using Get Equal (5)
13. Retry Delete (4) of record B: MicroKernel returns Status Code 84
14. End Transaction
15. Retry Delete (4) of record B: Successful
In Step 1, client 1’s Begin Concurrent Transaction operation specifies a generic bias value of 400 (multiple-record no-wait locks). This bias will be inherited by each non-biased Get or Step operation in this transaction. At this point, the MicroKernel has applied no locks to the file, its pages, or its records.
In Step 2, client 2’s Begin Transaction operation specifies a generic bias value of 100 (single-record wait locks). This bias will be inherited by each non-biased Get or Step operation in this transaction. The MicroKernel still has not applied any locks to the file, its pages, or its records.
In Step 3, client 1’s Get Equal operation specifies a bias value of 200 (single-record no-wait lock). The MicroKernel accepts this bias value rather than the inherited 400 (multiple no-wait record lock), because an individual operation’s specified bias value takes precedence over any inherited bias value.
In Step 4, client 2’s Get Equal operation (5) does not specify any bias value of its own; therefore, it inherits the single wait lock bias value of 100 from client 2’s Begin Concurrent Transaction operation (1119). Even though record A and record B are on the same page, both lock requests (Step 3 and Step 4) are successful because a record lock request locks only the specified record; it locks neither the data page on which the record is located, nor any associated index pages.
In Step 5, client 3’s non-transactional Get Equal operation (5) with no lock request is successful, because non-transactional reads are always successful (as long as the requested record exists).
In Step 6, client 3 attempts to Delete (4) record B; however, it cannot obtain the implicit record lock on record B required to delete the record, because client 2 holds an explicit lock on the record. Consequently, the MicroKernel returns Status Code 84 (Record or Page Locked) to client 3. Client 3 must then relinquish control and retry the Delete operation (if it wishes) later.
In Step 7, client 2 first successfully obtains an implicit record lock on record B. While record B is already explicitly locked by client 2 (because of Step 4’s inherited single wait lock bias from Step 2), no problem exists because both the explicit lock and the implicit lock belong to the same client. At this same time, client 2 also successfully obtains page locks on the data page containing record B and on the index page containing record B’s key value.
*Note: The data page locked by client 2 also contains record A, which is explicitly locked by client 1. However, as explained in Implicit Locks, record locks do not block page locks.
When the MicroKernel performs the actual Update operation (3) in Step 7, it writes the new, uncommitted images of the modified data and index pages as shadow pages to the file. At this point, the MicroKernel releases client 2’s explicit lock on record B. However, client 2 retains its implicit record lock on record B, as well as the implicit page locks it just obtained. Even after client 2 completes its Update operation (3) in Step 7, client 3 still cannot get the implicit record lock on record B, because now client 2 holds an implicit record lock on the record. Client 3 must continue its retry efforts.
If the clients are remote, client 2 puts a pending modification status on the file (in addition to the page locks, which are still necessary for concurrency control among clients local to client 2) before actually updating the file.
In Step 8, client 1 first successfully obtains an implicit record lock on record A. Even though record A’s data page has already been locked by client 2, no lock conflict exists, because page locks do not block record locks. (See Implicit Locks) Next, client 1 attempts to obtain an implicit page lock on the data page containing record A. This attempt fails because the data page has already been locked by client 2 in Step 7. Because the Begin Concurrent Transaction operation (1419) did not have a 500 bias specified, the MicroKernel retries the operation. (The MicroKernel also performs deadlock detection if the clients are local.)
Had client 1 issued its Begin Transaction operation with an additional 500 bias (1919), the MicroKernel would have returned control to the user immediately.
If the clients are remote, client 1 encounters the pending modification status set by client 2 in Step 7. Therefore, the MicroKernel retries the operation.
In Step 9, by ending its transaction, client 2 releases its implicit record lock on record B and the implicit page locks on the data index pages it locked in Step 5. At this point, the MicroKernel commits all the new page images that client 2 created during the transaction. These images now become a valid part of the file.
If the clients are remote, client 2 clears the pending modification status on the file, in addition to releasing the locks.
In Step 10, client 1’s continuing Update retries are finally successful, because client 2 no longer has record A’s data and index pages locked.
In Step 11, despite the fact that client 2 ended its transaction in Step 9 (thereby releasing all its locks), client 3 still cannot delete record B. Now, when client 3 attempts to delete the record, the MicroKernel’s passive concurrency control returns Status Code 80 (Conflict), because client 2 has modified record B since client 3 originally read it in Step 5. At this point, client 3 must re-read the record before it can retry the Delete operation.
In Step 12, client 3 reads record B again, getting an image that reflects the changes made to the record by client 2 in Step 7 and committed in Step 9.
In Step 13, client 3 again unsuccessfully attempts to delete record B, receiving a Status Code 84 from the MicroKernel. This status code reflects the fact that client 1, in updating record A, has an implicit page lock on the data and index pages containing record B (assuming, as stated earlier, that the same data page contains records A and B, and that the same index page contains the key values for those records).
In Step 14, client 1 ends its transaction, committing its changes and releasing its implicit page locks.
In Step 15, client 3 is finally able to delete record B.
Example 2
Example 2 shows how file locks and passive concurrency control interact. For further explanation of each step, see the paragraphs following the example.
1. Open file 1 (0)
2. Open file 2 (0)
3. Open file 3 (0)
4. Get record E, file 3 using a single record lock (105)
5. Open file 1 (0)
6. Begin Exclusive Transaction (19)
7. Get record B, file 1 (5)
8. Get record A, file 1 (5)
9. Update record A, file 1 (3) (Status Code 85, retrying)
10. Get record C, file 2 (5)
11. Update record C, file 2 (3)
12. Delete record B, file 1 (4)
13. End Transaction (20)
14. Retry Step 9 (successful)
In Step 4, client 1 obtains an explicit record lock on record E, file 3.
In Step 6, client 1 begins an exclusive transaction. Even though client 1 has three files open, the MicroKernel has not yet locked any of those files, nor does the MicroKernel release the explicit lock on record E in file 3 as a result of performing the Begin Transaction operation.
In Step 7, client 1 obtains a file lock on file 1 as a result of touching the file. (See File Locks) Step 7 would have failed if, in a previous step (for example, between Steps 5 and 6), client 2 had read a record from file 1 using an operation with a lock bias.
In Step 8, client 2 successfully reads record A from file 1. This read is successful because it does not request any lock. However, had the Get Equal operation (5) been issued with a lock bias, the operation would have failed because client 1 currently has file 1 locked.
In Step 9, client 2 cannot obtain an implicit record lock because client 1 has the file locked. Therefore, the MicroKernel returns Status Code 85 (File Locked) back to client 2. Client 2 must now relinquish control and retry Step 9 until client 1 ends or aborts its transaction (which happens in Step 13). (See When a Record Has Already Been Locked)
In Step 10, client 1 obtains a file lock on file 2.
In Step 13, client 1 releases file locks on files 1 and 2.
*Note: Client 1 never locked file 3 because it never touched that file in its exclusive transaction. In fact, even after Step 13, client 1 retains its explicit record lock on record E of file 3. Client 1 would have released record E only if the client had touched file 3 (thereby locking the entire file in the transaction).
In Step 14, client 2’s retry of the Update operation in Step 9 is finally successful.