1. Comprende funcionalidad de mecanismo de locking
Puntos Clave
- Comando LOCK: Controla acceso concurrent a recursos de datos compartidos
- Tipos de lock: Exclusivo (predeterminado), Compartido (#"S"), Escalante (#"E")
- Granularidad de lock: Los locks se aplican a nodos y afectan implícitamente relaciones padre/hijo
- Modos de lock: Locks incrementales, opciones de timeout, unlock automático
- Tabla de locks: Rastreo a nivel de sistema de todos los locks y solicitudes en espera
Notas Detalladas
Resumen
InterSystems IRIS proporciona mecanismos sofisticados de locking a través del comando LOCK para controlar acceso concurrent a recursos de datos. El concepto fundamental es que un lock es un recurso nombrado (típicamente coincidiendo con un nombre de variable global) que los procesos deben adquirir antes de modificar los datos correspondientes. Los locks siguen las mismas convenciones de nombres que las variables y pueden ser locales (específicos de proceso) o globales (cross-process). Cuando hace lock de un nodo específico como ^student(1,2), tiene un lock explícito solo en ese nodo, pero otros procesos están implícitamente impedidos de hacer lock de nodos padre (^student(1)) o nodos hijo (^student(1,2,3)). Este comportamiento de lock jerárquico previene conflictos a través del árbol de subscripts.
El sistema soporta tres tipos primarios de lock: exclusivo (predeterminado), compartido (#"S"), y escalante (#"E"). Los locks exclusivos limitan un recurso a un proceso, mientras que los locks compartidos permiten que múltiples procesos mantengan locks no conflictivos simultáneamente. Un lock compartido existente previene que otros procesos apliquen un lock exclusivo, y viceversa. Sin embargo, un proceso puede actualizar su propio lock compartido a exclusivo. Los locks escalantes proporcionan escalación automática de lock cuando el número de locks a un nivel de subscript alcanza el umbral (predeterminado 1000), haciendo lock automáticamente del nodo padre para prevenir desbordamiento de tabla de locks.
Las operaciones de lock usan tres indicadores: ningún carácter (unlock de todos los locks previos luego lock), + (lock incremental sin unlock), y - (unlock/decrement). El parámetro de timeout (especificado como :seconds) es crítico para prevenir cuelgues de proceso; sin un timeout, las solicitudes de lock esperan indefinidamente. Cuando es exitoso, $TEST se establece a 1; en timeout, $TEST se convierte en 0. La tabla de locks mantiene información a nivel de sistema sobre todos los locks incluyendo conteos exclusivo/compartido, estado escalante, estado de delock, y procesos en espera. Los locks se liberan automáticamente cuando un proceso termina, y dentro de transacciones, los unlocks pueden diferirse hasta commit/rollback.
Referencias de Documentación
2. Aplica mejores prácticas para uso de locks
Puntos Clave
- Siempre usar timeouts: Previene cuelgues indefinidos de proceso (LOCK ^data:10)
- Minimizar duración de lock: Adquirir locks tarde, liberar temprano para reducir contención
- Evitar deadlocks: Nunca actualizar compartido a exclusivo con +; usar ordenamiento de lock consistente
- Usar locks con subscripts: LOCK ^student(1) rinde mejor que LOCK ^student
- Monitorear tabla de locks: Usar Management Portal o ^LOCKTAB para diagnosticar contención
Notas Detalladas
Resumen
Las mejores prácticas para uso de locks se centran en prevenir deadlocks, minimizar contención, y mantener responsividad del sistema. La práctica más crítica es siempre especificar valores de timeout al adquirir locks. Sin timeouts, un comando LOCK espera indefinidamente si otro proceso mantiene un lock conflictivo, potencialmente colgando el proceso. Un timeout de 0 hace un intento e inmediatamente retorna, mientras que valores positivos esperan el número especificado de segundos. Después de emitir un lock con timeout, siempre verifique $TEST para verificar éxito antes de proceder con operaciones críticas.
La prevención de deadlock requiere comprender el patrón peligroso: solicitar un lock exclusivo cuando se mantiene un lock compartido. Si el Proceso A mantiene un lock compartido en ^data(1) y el Proceso B también mantiene un lock compartido en ^data(1), y ambos luego solicitan locks exclusivos con LOCK +^data(1), ninguno puede proceder - cada uno espera que el otro libere su lock compartido. La solución es usar LOCK ^data(1) (sin el signo más) que primero libera el lock compartido antes de solicitar el lock exclusivo. El ordenamiento consistente de locks a través de todos los procesos también previene deadlocks: si todos los procesos hacen lock de recursos en la misma secuencia (ej., siempre lock ^indexA antes de ^indexB), no pueden ocurrir condiciones de espera circular.
Las mejores prácticas de rendimiento incluyen usar nombres de lock con subscripts siempre que sea posible (^student(1) en lugar de ^student) y minimizar la duración de lock adquiriendo locks lo más tarde posible y liberándolos tan pronto como sea seguro. La granularidad de lock importa: hacer lock al nivel apropiado balancea concurrencia (locks de grano fino permiten más operaciones paralelas) contra overhead (demasiados locks consumen espacio de tabla de locks). Use locks escalantes (#"E") al aplicar muchos locks al mismo nivel de subscript para prevenir desbordamiento de tabla de locks. Dentro de transacciones, comprenda que los unlocks de locks no incrementados se difieren hasta commit de transacción a menos que especifique unlock inmediato (#"I"). El monitoreo regular de la tabla de locks a través del Management Portal (System Operation > Locks > View Locks) o la utilidad ^LOCKTAB ayuda a identificar cuellos de botella de contención y situaciones de deadlock antes de que impacten los sistemas de producción.
Referencias de Documentación
3. Selecciona entre locks a nivel de fila y a nivel de tabla apropiadamente
Puntos Clave
- Locks a nivel de fila: Predeterminado de SQL; lock de registros individuales para alta concurrencia
- Locks a nivel de tabla: Escalación de lock en umbral (predeterminado 1000 locks)
- Umbral de lock: Configurable vía $SYSTEM.SQL.Util.SetOption("LockThreshold")
- Locks de transacción: Locking automático para operaciones INSERT, UPDATE, DELETE
- Escalación de lock: Previene desbordamiento de tabla de locks escalando a nodo padre
Notas Detalladas
Resumen
InterSystems IRIS automáticamente gestiona la elección entre locks a nivel de fila y nivel de tabla durante operaciones SQL, con la capacidad de configurar el umbral de escalación basado en requisitos de aplicación. El locking a nivel de fila es el predeterminado para operaciones DML de SQL (INSERT, UPDATE, DELETE) dentro de transacciones. Cada modificación de fila adquiere un lock en el valor de dato único, permitiendo alta concurrencia ya que diferentes procesos pueden modificar simultáneamente diferentes filas en la misma tabla. Estos locks se mantienen durante la duración de la transacción para prevenir conflictos y asegurar integridad de datos. Por ejemplo, si un proceso elimina un valor de dato único, este valor permanece bloqueado hasta que la transacción se completa, previniendo que otro proceso inserte un registro con el mismo valor (lo cual podría causar un duplicado después de rollback).
La escalación de lock ocurre automáticamente cuando el número de locks a nivel de fila para una sola tabla excede el umbral de lock. El umbral predeterminado es 1000 locks por tabla. Cuando se solicita el lock 1001, el sistema escala a un lock a nivel de tabla, liberando todos los locks de fila individuales y adquiriendo un solo lock en el nodo padre. Este lock de tabla persiste durante la duración de la transacción, y las operaciones de fila subsiguientes incrementan el conteo de lock de tabla en lugar de crear nuevos locks de fila. La escalación de lock previene desbordamiento de tabla de locks pero reduce concurrencia ya que la tabla entera está bloqueada en lugar de filas individuales. El umbral de lock es configurable usando $SYSTEM.SQL.Util.SetOption("LockThreshold",value) que cambia tanto el valor actual a nivel de sistema como la configuración del archivo de configuración. Puede consultar el umbral actual con $SYSTEM.SQL.Util.GetOption("LockThreshold").
Elegir la granularidad de lock apropiada depende de patrones de transacción. Aplicaciones con transacciones cortas modificando pocas filas se benefician de locks a nivel de fila maximizando concurrencia. Operaciones batch modificando grandes números de filas podrían beneficiarse de un umbral de lock más bajo o incluso locks explícitos a nivel de tabla para reducir overhead de gestión de locks. Sin embargo, bajar el umbral demasiado aumenta la probabilidad de escalación de lock, que bloquea a otros procesos de acceder a cualquier fila en la tabla. En ObjectScript, puede usar locks escalantes explícitamente con el tipo de lock #"E": LOCK +^data(1,1)#"E",+^data(1,2)#"E",... Cuando se alcanza el umbral, estos automáticamente escalan a ^data(1). Comprender el mecanismo de escalación permite a los desarrolladores diseñar aplicaciones que balanceen necesidades de concurrencia contra restricciones de tamaño de tabla de locks. El argumento de restricción %NOLOCK en declaraciones SQL evita locking automático cuando tiene gestión de lock externa u operaciones de solo lectura.
Referencias de Documentación
Resumen de Preparación para el Examen
Conceptos Críticos a Dominar:
- Fundamentos de Lock: Sintaxis de comando LOCK, tipos de lock (exclusivo/compartido/escalante), uso de timeout
- Locking Jerárquico: Comprender relaciones de lock de nodos padre/hijo y locking implícito
- Prevención de Deadlock: Nunca actualizar compartido a exclusivo con +; usar ordenamiento de lock consistente
- Gestión de Tabla de Locks: Ver locks vía Management Portal y utilidad ^LOCKTAB
- Locks de Fila vs Tabla: Comprender escalación automática en umbral y cuándo usar cada uno
- Comportamiento de Transacción: Locks diferidos en transacciones, locking incremental, liberación automática
Escenarios Comunes de Examen:
- Identificar situaciones de deadlock y cómo prevenirlas
- Elegir granularidad de lock apropiada para diferentes casos de uso
- Comprender cuándo los locks escalan de nivel de fila a nivel de tabla
- Depurar contención de lock usando herramientas de monitoreo de tabla de locks
- Determinar valores de timeout apropiados y estrategias de manejo de errores
- Reconocer indicadores de tipo de lock (#"S", #"E", #"I", #"D") y sus efectos
Recomendaciones de Práctica Práctica:
- Practicar comando LOCK con varios escenarios de timeout y verificar $TEST
- Crear situaciones intencionales de deadlock y resolverlas
- Usar Management Portal para monitorear locks durante operaciones concurrentes
- Experimentar con escalación de lock estableciendo valores bajos de LockThreshold
- Probar locks compartidos vs exclusivos con múltiples sesiones de Terminal
- Practicar locking incremental y observar conteos de lock en tabla de locks
- Implementar locking basado en transacción con comportamiento de unlock diferido
- Usar ^$LOCK para consultar programáticamente información de lock
Sintaxis Clave a Memorizar:
Monitoreo Importante de Tabla de Locks:
- Management Portal: System Operation > Locks > View Locks
- Utilidad ^LOCKTAB: DO ^LOCKTAB (desde namespace %SYS)
- Estados de lock: Exclusive, Shared, WaitExclusiveExact, WaitExclusiveParent, WaitExclusiveChild
- Valores ModeCount: Exclusive/n, Shared/n, Exclusive_e, Shared_e, ->Delock
Interacción de Transacción y Lock:
- Los locks dentro de transacciones se mantienen hasta COMMIT o ROLLBACK
- Comportamiento de unlock predeterminado en transacción: difiere liberación hasta fin de transacción
- Usar #"I" para unlock inmediato dentro de transacción
- El umbral de escalación de lock se aplica a locks por tabla por transacción
- Locks automáticos para INSERT, UPDATE, DELETE a menos que se especifique %NOLOCK