Skip to main content

$SEQUENCE (ObjectScript)

Increments a global variable shared by multiple processes.

Synopsis

$SEQUENCE(gvar)
$SEQ(gvar)

SET $SEQUENCE(gvar)=value
SET $SEQ(gvar)=value

Arguments

Argument Description
gvar

The variable whose value is to be incremented. Commonly, gvar is a global variable (^gvar), either subscripted or unsubscripted. The variable need not be defined. If gvar is not defined, or is set to the null string (""), $SEQUENCE treats it as having an initial value of zero and increments accordingly, returning a value of 1.

You cannot specify a literal value for gvar. You cannot specify a simple object property reference as gvar; you can specify a multidimensional property reference as gvar with the syntax obj.property.

value Optional — An expression that evaluates to an integer or the empty string. Used with SET $SEQUENCE syntax.

Description

$SEQUENCE and $INCREMENT can both increment local variables, global variables, or process-private globals. $SEQUENCE is typically used on globals.

$SEQUENCE provides a fast way for multiple processes to obtain unique (non-duplicate) integer indexes for the same global variable. For each process, $SEQUENCE allocates a sequence (range) of integer values. $SEQUENCE uses this allocated sequence to assign a value to gvar and returns this gvar value. Subsequent calls to $SEQUENCE increment to the next value in the allocated sequence for that process. When a process consumes all of the integer values in its allocated sequence, its next call to $SEQUENCE automatically allocates a new sequence of integer values. $SEQUENCE automatically determines the size of the sequence of integer values to allocate. It determines the size of the allocated sequence separately for each sequence allocation. In some cases, this allocated sequence may be a single integer.

$SEQUENCE performs as an atomic operation (and so does not require the use of the LOCK command).

$SEQUENCE is intended to be used when multiple processes concurrently increment the same global. $SEQUENCE allocates to each concurrent process a unique range of values for the gvar global. Each process can then call $SEQUENCE to assign sequential values from its allocated range of values.

The size of the sequence that $SEQUENCE allocates to a process depends on an internal timestamp. When a process invokes $SEQUENCE for the second time, InterSystems IRIS compares the prior timestamp with the current time. Depending on the duration between these $SEQUENCE calls, InterSystems IRIS allocates either a single increment or a calculated sequence of increments to the process:

  • Allocated sequence is 1: $SEQUENCE behaves like $INCREMENT.

  • Allocated sequence is > 1: $SEQUENCE uses this per-process sequence of increments. Each process uses its allocated sequence, then is assigned a new sequence.

For example, Process A and Process B are both incrementing the same global. The first time each process increments the global it is a single increment. The next time each process increments the global, InterSystems IRIS compares the two $SEQUENCE operations and calculates a sequence of increments (this sequence may be one integer). Subsequent $SEQUENCE operations use up these per-process sequences before re-allocating increments. This might result in increments such as the following: A1, B2 (single increments setting the clock), A3 (compares A1 & A3, allocates 4, 5, 6, 7 to Process A), B8 (compares B2 and B8, allocates 9, 10, 11 to Process B). The full increment sequence might be as follows: A1, B2, A3, A4, B8, A5, A6, B9, A7, B10, B11.

If a process does not use all of its allocated sequence, the remaining numbers are unused, leaving gaps in the increment sequence.

For further details on using $SEQUENCE with global variables, see Using Multidimensional Storage (Globals).

Arguments

gvar

A variable containing an integer value to be incremented. The variable does not need to be defined; the first call to $SEQUENCE defines an undefined variable as 0 then increments its value to 1. The gvar value must be a positive or negative integer.

Commonly, the gvar argument is a global variable, either subscripted or unsubscripted: ^gvar. It can contain an extended global reference. If a subscripted global variable, it can be specified using a naked global reference.

The gvar argument can be a local variable or process-private global. However, because $SEQUENCE is intended for use across processes, this usage is not meaningful, in most cases. Using $SEQUENCE on a local variable or process-private global is the same as using $INCREMENT with a numeric increment of 1. The $SEQUENCE restrictions described below concerning locking, journaling, and transaction rollback do not apply to local variables or process-private globals. Using $SEQUENCE on a local variable or process-private global has the same error behavior as $INCREMENT; this is different from the error behavior for $SEQUENCE on a global variable, as described in the next section.

The gvar argument can be a multidimensional property reference. For example, $SEQUENCE(..Count). It cannot be a non-multidimensional object property. Attempting to increment a non-multidimensional object property results in an <OBJECT DISPATCH> error.

$SEQUENCE cannot increment special variables, even those that can be modified using SET. Attempting to increment a special variable results in a <SYNTAX> error.

value

Used with SET $SEQUENCE to specify a starting integer for sequential increment. This value can be any expression, but must evaluate to an empty string or a positive or negative integer. A non-numeric string (such as “centimeters”) evaluates to 0. A mixed numeric string (such as “6centimeters”) evaluates to the integer portion: 6. A string that evaluates to a non-integer numeric (such as “6.5centimeters”) generates an <ILLEGAL VALUE> error.

SET $SEQUENCE

You can use SET $SEQUENCE to kill or reset a $SEQUENCE global. SET $SEQUENCE resets the global variable and deallocates sequences of integers allocated to other processes.

  • SET $SEQUENCE(^gvar)="" kills the specified global node and notifies all jobs with cached $SEQUENCE numbers to purge their current increment value. The first call to $SEQUENCE increments to 1. SET $SEQUENCE(^gvar)="" only kills the specified global node; it does not kill that node’s descendants (if any).

  • SET $SEQUENCE(^gvar)=n (where n is an integer) resets the specified global node to n, and notifies all jobs with cached $SEQUENCE numbers to purge their current increment value. Subsequent invocations of $SEQUENCE on all jobs will use the new n increment starting value.

    By default, $SEQUENCE assigns positive integers, beginning with 1. However, $SEQUENCE can be set to a negative integer; negative integers are incremented towards zero. If $SEQUENCE was set to a negative integer, a subsequent call can assign zero as an increment.

    If SET $SEQUENCE attempts to set ^gvar to a non-integer numeric value generates an <ILLEGAL VALUE> error. If SET $SEQUENCE attempts to set ^gvar to a non-numeric string, ^gvar is set to 0.

You cannot use KILL ^gvar or SET ^gvar to kill or reset a $SEQUENCE global because these commands do not deallocate sequences of integers allocated to processes.

Incrementing Very Large Numbers

The integers returned by $SEQUENCE are in the range -9223372036854775807 to 9223372036854775806 (-2**63+1 to 2**63-2). Attempting a SET $SEQUENCE on a global variable with an integer beyond this range generates an <ILLEGAL VALUE> error.

In the following example, $SEQUENCE on a global variable can be set to 9.223372036854775800E18, but incrementing this number past the range limit generates a <MAXINCREMENT> error. You can run this example repeatedly to perform “slow increments” and “fast increments”. Note that “fast increments” in this example may result in <MAXINCREMENT> before actually incrementing to the range limit, because $SEQUENCE is attempting to allocate a sequence of numbers beyond the range limit:

  TRY {
  SET rand=$RANDOM(2)
  SET $SEQUENCE(^bignum)=9.223372036854775800E18
    IF rand=0 {  WRITE "slow increments:",!
    FOR x=1:1:10 {WRITE $SEQUENCE(^bignum)," increment #",x,!
                HANG .5 }
    }
    IF rand=1 {WRITE "fast increments:",!
    FOR i=1:1:10 {WRITE $SEQUENCE(^bignum)," increment #",i,!}
    }
  }
  CATCH exp { WRITE !,"In the CATCH block",!
                IF 1=exp.%IsA("%Exception.SystemException") {
                  WRITE "System exception",!
                  WRITE "Name: ",$ZCVT(exp.Name,"O","HTML"),!
                  WRITE "Location: ",exp.Location,!
                }
                ELSE { WRITE "unknown error",! }
  }

These types of errors only occur when incrementing a global variable.

$SEQUENCE or $INCREMENT?

Both $SEQUENCE and $INCREMENT allow multiple processes to assign unique integers to the same global variable, but $SEQUENCE commonly provides better performance. The order in which $SEQUENCE assigns indexes is different from the $INCREMENT order. $SEQUENCE can allocate a sequential range of increments to a process, rather than the $INCREMENT behavior of allocating single integer increments to each process. This can substantially improve performance by reducing process collision and synchronization. It can also improve data block performance when inserting records, because sequential record IDs are grouped by process.

$SEQUENCE is intended specifically for integer increment operations involving multiple simultaneous processes. $INCREMENT is a more general increment/decrement function:

  • $SEQUENCE increments global variables. $INCREMENT increments local variables, global variables, or process-private globals.

  • $SEQUENCE increments any numeric value by 1. $INCREMENT increments or decrements any numeric value by any specified numeric value.

  • $SEQUENCE can allocate a range of increments to a process. $INCREMENT allocates only a single increment.

  • SET $SEQUENCE can be used to change or undefine (kill) a global. $INCREMENT cannot be used on the left side of the SET command.

By default, InterSystems IRIS SQL automatically performs RowID assignment using $SEQUENCE, allowing for the rapid simultaneous populating of the table by multiple processes. You can configure InterSystems IRIS SQL to perform RowID assignment using $INCREMENT.

$SEQUENCE and Transaction Processing

  • Locking: The common usage for $SEQUENCE is to increment a counter before adding a new entry to a database. $SEQUENCE provides a way to do this very quickly, avoiding the use of the LOCK command. The gvar may be incremented by one process within a transaction and, while that transaction is still processing, be incremented by another process in a parallel transaction.

  • Rollback: Calls to $SEQUENCE are not journaled. Therefore, rolling back a transaction will not change the value of gvar. Any integer values allocated by $SEQUENCE during a rolled back transaction will not be available for allocation by any future $SEQUENCE call.

For further details on using $SEQUENCE in a distributed database environment, refer to Use the $Increment Function for Application Counters.

See Also

FeedbackOpens in a new tab