Skip to main content

locktype

locktype

A letter code specifying the type of lock to apply or remove. locktype is an optional argument; if you omit locktype, the lock type defaults to an exclusive non-escalating lock. If you omit locktype, you must omit the pound sign (#) prefix. If you specify locktype, the syntax for lock type is a mandatory pound sign (#), followed by quotation marks enclosing one or more lock type letter codes. Lock type letter codes can be specified in any order and are not case-sensitive. The following are the lock type letter codes:

  • S: Shared lock

    Allows multiple processes to simultaneously hold nonconflicting locks on the same resource. For example, two (or more) processes may simultaneously hold shared locks on the same resource, but an exclusive lock limits the resource to one process. An existing shared lock prevents all other processes from applying an exclusive lock, and an existing exclusive lock prevents all other processes from applying a shared lock on that resource. However, a process can first apply a shared lock on a resource and then the same process can apply an exclusive lock on the resource, upgrading the lock from shared to exclusive. Shared and Exclusive lock counts are independent. Therefore, to release such a resource it is necessary to release both the exclusive lock and the shared lock. All locking and unlocking operations that are not specified as shared (“S”) default to exclusive.

    A shared lock may be incremental; that is, a process may issue multiple shared locks on the same resource. You may specify a shared lock as escalating (“SE”) when locking and unlocking. When unlocking a shared lock, you may specify the unlock as immediate (“SI”) or deferred (“SD”). To view the current shared locks with their increment counts for escalating and non-escalating lock types, refer to the system-wide lock table, described in Lock Management.

  • E: Escalating lock

    Allows you to apply a large number of concurrent locks without overflowing the lock table. By default, locks are non-escalating. When applying a lock, you can use locktype “E” to designate that lock as escalating. When releasing an escalating lock, you must specify locktype “E” in the unlock statement. You can designate both exclusive locks and shared (“S”) locks as escalating.

    Commonly, you would use escalating locks when applying a large number of concurrent locks at the same subscript level. For example LOCK +^mylock(1,1)#"E",+^mylock(1,2)#"E",+^mylock(1,3)#"E"....

    The same lock can be concurrently applied as a non-escalating lock and as an escalating lock. For example, ^mylock(1,1) and ^mylock(1,1)#"E". InterSystems IRIS counts locks issued with locktype “E” separately in the lock table. For information on how escalating and non-escalating locks are represented in the lock table, refer to Lock Management.

    When the number of “E” locks at a subscript level reaches a threshold number, the next “E” lock requested for that subscript level automatically attempts to lock the parent node (the next higher subscript level). If it cannot, no escalation occurs. If it successfully locks the parent node, it establishes one parent node lock with a lock count corresponding to the number of locks at the lower subscript level, plus 1. The locks at the lower subscript level are released. Subsequent “E” lock requests to the lower subscript level further increment the lock count of this parent node lock. You must unlock all “E” locks that you have applied to decrement the parent node lock count to 0 and de-escalate to the lower subscript level. The default lock threshold is 1000 locks; lock escalation occurs when the 1001st lock is requested.

    Note that once locking is escalated, lock operations preserve only the number of locks applied, not what specific resources were locked. Therefore, failing to unlock the same resources that you locked can cause “E” lock counts to get out of sync.

    In the following example, lock escalation occurs when the program applies the lock threshold + 1 “E” lock. This example shows that lock escalation both applies a lock on the next-higher subscript level and releases the locks on the lower subscript level:

    Main
      TSTART
      SET thold=$SYSTEM.SQL.Util.GetOption("LockThreshold") 
      WRITE "lock escalation threshold is ",thold,!
      SET almost=thold-5
      FOR i=1:1:thold+5 { LOCK +dummy(1,i)#"E"
         IF i>almost {
           IF ^$LOCK("dummy(1,"_i_")","OWNER") '= "" {WRITE "lower level lock applied at ",i,"th lock ",! }
           ELSEIF ^$LOCK("dummy(1)","OWNER") '= ""   {WRITE "lock escalation",!
                                                      WRITE "higher level lock applied at ",i,"th lock ",!
                                                      QUIT }
           ELSE {WRITE "No locks applied",! }
         }
      }
      TCOMMIT

    Note that only “E” locks are counted towards lock escalation. The following example applies both default (non-“E”) locks and “E” locks on the same variable. Lock escalation only occurs when the total number of “E” locks on the variable reaches the lock threshold:

    Main
      TSTART
      SET thold=$SYSTEM.SQL.Util.GetOption("LockThreshold")
      WRITE "lock escalation threshold is ",thold,!
      SET noE=17
      WRITE "setting ",noE," non-escalating locks",!
      FOR i=1:1:thold+noE { IF i < noE {LOCK +a(6,i)}
                      ELSE {LOCK +a(6,i)#"E"}
        IF ^$LOCK("a(6)","OWNER") '= "" {
           WRITE "lock escalation on lock a(6,",i,")",!
           QUIT }
      }
      TCOMMIT

    Unlocking “E” locks is the reverse of the above. When locking is escalated, unlocks at the child level decrement the lock count of the parent node lock until it reaches zero (and is unlocked); these unlocks decrementing a count, they are not matched to specific locks. When the parent node lock count reaches 0, the parent node lock is removed and “E” locking de-escalates to the lower subscript level. Any subsequent locks at the lower subscript level create specific locks at that level.

    The “E” locktype can be combined with any other locktype. For example, “SE”, “ED”, “EI”, “SED”, “SEI”. When combined with the “I” locktype it permits unlocks of “E” locks to occur immediately when invoked, rather than at the end of the current transaction. This “EI” locktype can minimize situations where locking is escalated.

    Commonly, “E” locks are automatically applied for SQL INSERT, UPDATE, and DELETE operations within a transaction. However, there are specific limitations on SQL data definition structures that support “E” locking. Refer to the specific SQL commands for details.

  • I: Immediate unlock

    Immediately releases a lock, rather than waiting until the end of a transaction:

    • Specifying “I” when unlocking a non-incremented (lock count 1) lock immediately releases the lock. By default, an unlock does not immediately release a non-incremented lock. Instead, when you unlock a non-incremented lock InterSystems IRIS maintains that lock in a delock state until the end of the transaction. Specifying “I” overrides this default behavior.

    • Specifying “I” when unlocking an incremented lock (lock count > 1) immediately releases the incremental lock, decrementing the lock count by 1. This is the same behavior as a default unlock of an incremented lock.

    The “I” locktype is used when performing an unlock during a transaction. It has the same effect on InterSystems IRIS unlock behavior whether the lock was applied within the transaction or outside of the transaction. The “I” locktype performs no operation if the unlock occurs outside of a transaction. Outside of a transaction, an unlock always immediately releases a specified lock.

    “I” can only be specified for an unlock operation; it cannot be specified for a lock operation. “I” can be specified for an unlock of a shared lock (#"SI") or an exclusive lock (#"I"). Locktypes “I” and “D” are mutually exclusive. “IE” can be used to immediately unlock an escalating lock.

    This immediate unlock is shown in the following example:

      TSTART
      LOCK +^a(1)      // apply lock ^a(1)
      LOCK -^a(1)      // remove (unlock) ^a(1)
                       // An unlock without a locktype defers the unlock
                       // of a non-incremented lock to the end of the transaction.
      WRITE "Default unlock within a transaction.",!,"Go look at the Lock Table",!
      HANG 10          // This HANG allows you to view the current Lock Table
      LOCK +^a(1)      // reapply lock ^a(1)
      LOCK -^a(1)#"I"  // remove (unlock) lock ^a(1) immediately
                       // this removes ^a(1) from the lock table immediately
                       // without waiting for the end of the transaction
      WRITE "Immediate unlock within a transaction.",!,"Go look at the Lock Table",!
      HANG 10          // This HANG allows you to view the current Lock Table
                       // while still in the transaction
      TCOMMIT
  • D: Deferred unlock

    Controls when an unlocked lock is released during a transaction. The unlock state is deferred to the state of the previous unlock of that lock. Therefore, specifying locktype “D” when unlocking a lock may result in either an immediate unlock or a lock placed in delock state until the end of the transaction, depending on the history of the lock during that transaction. The behavior of a lock that has been locked/unlocked more than once differs from the behavior of a lock that has only been locked once during the current transaction.

    The “D” unlock is only meaningful for an unlock that releases a lock (lock count 1), not an unlock that decrements a lock (lock count > 1). An unlock that decrements a lock is always immediately released.

    “D” can only be specified for an unlock operation. “D” can be specified for a shared lock (#"SD") or an exclusive lock (#"D"). “D” can be specified for a escalating (“E”) lock, but, of course, the unlock must also be specified as escalating (“ED”). Lock types “D” and “I” are mutually exclusive.

    This use of “D” unlock within a transaction is shown in the following examples. The HANG commands give you time to check the lock’s ModeCount in the Lock Table.

    If the lock was only applied once during the current transaction, a “D” unlock immediately releases the lock. This is the same as “I” behavior. This is shown in the following example:

      TSTART
      LOCK +^a(1)      // Lock Table ModeCount: Exclusive
      LOCK -^a(1)#"D"  // Lock Table ModeCount: null (immediate unlock)
      HANG 10
      TCOMMIT

    If the lock was applied more than once during the current transaction, a “D” unlock reverts to the prior unlock state.

    • If the last unlock was a standard unlock, the “D” unlock reverts unlock behavior to that prior unlock’s behavior — to defer unlock until the end of the transaction. This is shown in the following examples:

        TSTART
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)      // Lock Table ModeCount: Exclusive
           WRITE "1st unlock",! HANG 5
        LOCK -^a(1)#"D"  // Lock Table ModeCount: Exclusive->Delock
           WRITE "2nd unlock",! HANG 5
        TCOMMIT
        TSTART
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)      // Lock Table ModeCount: Exclusive->Delock
           WRITE "1st unlock",! HANG 5
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)#"D"  // Lock Table ModeCount: Exclusive->Delock
           WRITE "2nd unlock",! HANG 5
        TCOMMIT
        TSTART
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)#"I"  // Lock Table ModeCount: Exclusive/2
           WRITE "1st unlock",! HANG 5
        LOCK -^a(1)      // Lock Table ModeCount: Exclusive
           WRITE "2nd unlock",! HANG 5
        LOCK -^a(1)#"D"  // Lock Table ModeCount: Exclusive->Delock
           WRITE "3rd unlock",! HANG 5
        TCOMMIT
    • If the last unlock was an “I” unlock, the “D” unlock reverts unlock behavior to that prior unlock’s behavior — to immediately unlock the lock. This is shown in the following examples:

        TSTART
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)#"I"  // Lock Table ModeCount: null (immediate unlock)
           WRITE "1st unlock",! HANG 5
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)#"D"  // Lock Table ModeCount: null (immediate unlock)
           WRITE "2nd unlock",! HANG 5
        TCOMMIT
        TSTART
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)#"I"  // Lock Table ModeCount: Exclusive
           WRITE "1st unlock",! HANG 5
        LOCK -^a(1)#"D"  // Lock Table ModeCount: null (immediate unlock)
           WRITE "2nd unlock",! HANG 5
        TCOMMIT
    • If the last unlock was a “D” unlock, the “D” unlock follows the behavior of the last prior non-“D” lock:

        TSTART
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)#"D"  // Lock Table ModeCount: Exclusive
           WRITE "1st unlock",! HANG 5
        LOCK -^a(1)#"D"  // Lock Table ModeCount: null (immediate unlock)
           WRITE "2nd unlock",! HANG 5
        TCOMMIT
        TSTART
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)      // Lock Table ModeCount: Exclusive/2
           WRITE "1st unlock",! HANG 5
        LOCK -^a(1)#"D"  // Lock Table ModeCount: Exclusive
           WRITE "2nd unlock",! HANG 5
        LOCK -^a(1)#"D"  // Lock Table ModeCount: Exclusive->Delock
           WRITE "3rd unlock",! HANG 5
        TCOMMIT
        TSTART
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK +^a(1)      // Lock Table ModeCount: Exclusive
        LOCK -^a(1)#"I"  // Lock Table ModeCount: Exclusive/2
           WRITE "1st unlock",! HANG 5
        LOCK -^a(1)#"D"  // Lock Table ModeCount: Exclusive
           WRITE "2nd unlock",! HANG 5
        LOCK -^a(1)#"D"  // Lock Table ModeCount: null (immediate unlock)
           WRITE "3rd unlock",! HANG 5
        TCOMMIT
FeedbackOpens in a new tab