Orientation Guide for Server-Side Programming
Locking and Concurrency Control
An important feature of any multi-process system is concurrency control, the ability to prevent different processes from changing a specific element of data at the same time, resulting in corruption. Consequently, ObjectScript provides a lock management system. This section provides a brief summary.
The basic locking mechanism is the LOCK command. The purpose of this command is to delay activity in one process until another process has signaled that it is OK to proceed.
It is important to understand that a lock does not, by itself, prevent other processes from modifying the associated data; that is, InterSystems IRIS does not enforce unilateral locking. Locking works only by convention: it requires that mutually competing processes all implement locking with the same lock names.
You can use the LOCK command to create locks (replacing all previous locks owed by the process), to add locks, to remove specific locks, and to remove all locks owned by the process.
For the purpose of this simple discussion, the LOCK command uses the following arguments:
The lock name. Lock names are arbitrary, but by universal convention, programmers use lock names that are identical to the names of the item to be locked. Usually the item to be locked is a global or a node of a global.
The optional lock type (to create a non-default type of lock). There are several lock types, with different behaviors.
An optional timeout argument, which specifies how long to wait before the attempted lock operation times out. By default, InterSystems IRIS waits indefinitely.
The following describes a common lock scenario: Process A issues the LOCK command, and InterSystems IRIS attempts to create a lock. If process B already has a lock with the given lock name, process A pauses. Specifically, the LOCK command in process A does not return, and no successive lines of code can be executed. When the process B releases the lock, the LOCK command in process A finally returns and execution continues.
The system automatically uses the LOCK command internally in many cases, such as when you work with persistent objects (discussed later in this book) or when you use certain InterSystems SQL commands.
InterSystems IRIS maintains a system-wide, in-memory table that records all current locks and the processes that own them. This table the lock table is accessible via the Management Portal, where you can view the locks and (in rare cases, if needed) remove them. Note that any given process can own multiple locks, with different lock names (or even multiple locks with the same lock name).
When a process ends, the system automatically releases all locks that the process owns. Thus it is not generally necessary to remove locks via the Management Portal, except in the case of an application error.
The lock table cannot exceed a fixed size, which you can specify. For information, see “Monitoring Locks
” in the Monitoring Guide
. Consequently, it is possible for the lock table to fill up, such that no further locks are possible. If this occurs, InterSystems IRIS writes the following message to the messages.log
Filling the lock table is not generally considered to be an application error; InterSystems IRIS also provides a lock queue, and processes wait until there is space to add their locks to the lock table.
However, if two processes each assert an incremental lock on a variable already locked by the other process, that is a condition called deadlock
and it is
considered an application programming error. For details, see “Avoiding Deadlock
” in the chapter “Lock Management” in Using ObjectScript
When you lock an array, you can lock either the entire array or one or more nodes in the array. When you lock an array node, other processes are blocked from locking any node that is subordinate to that node. Other processes are also blocked from locking the direct ancestors of the locked node.
The following figure shows an example:
When you create a lock, you specify a combination of lock type codes, which control the nature of the lock. This section discusses some of the key concepts of lock types.
Depending on the lock type, it is possible to create multiple locks with the same lock name. These locks can be owned by the same process or different processes, again depending on the lock type. The lock table displays information for all of them.
Any lock is either exclusive (the default) or shared. These types have the following significance:
While one process has an exclusive lock (with a given lock name), no other process can acquire any lock with that lock name.
While one process has a shared lock (with a given lock name), other processes can acquire shared locks with that lock name, but no other process can acquire an exclusive lock with that lock name.
In general, the purpose of an exclusive lock is to indicate that you intend to modify a value and that other processes should not attempt to read or modify that value. The purpose of a shared lock is to indicate that you intend to read a value and that other processes should not attempt to modify that value; they can, however, read the value.
Any lock is also either non-escalating
(the default) or escalating
. The purpose of escalating locks is to make it easier to manage large numbers of locks, which consume memory and which increase the chance of filling the lock table
. You use escalating locks when you lock multiple nodes of the same array. For escalating locks, if a given process has created more than a specific number (by default, 1000) of locks on sibling nodes of a given array, InterSystems IRIS removes all the individual lock names and replaces them with a new lock at the parent level. For example, you might have 1000 locks of the form ^MyGlobal("sales","EU",salesdate)
represents dates. When the same process attempts to create another lock of this form (and these locks are all escalating), InterSystems IRIS removes all these locks and replaces them with a lock of the name ^MyGlobal("sales","EU")
. The lock table maintains the lock count for this new lock. This lock count is currently 1001, but when you add additional lock names of the same form, the lock table increments the lock count for the lock name ^MyGlobal("sales","EU")
. Similarly, when you remove lock names of the same form, the lock table decrements this lock count.
There are additional subtypes of locks that InterSystems IRIS treats in specific ways within transactions. For details on these and for more information on locks in general, see LOCK
in the ObjectScript Reference
. For information on specifying the lock threshold (which by default is 1000), see “LockThreshold
” in the Configuration Parameter File Reference
Content Date/Time: 2019-09-19 06:44:29