Question
· Oct 23, 2023

Release System Locks

Hi Guys,

We currently for reason I'm getting too many locks in the system (around 990 locks) and is making the system slow

 

 

 

most of these locks are on globals 


I have a method that sets values in some globals every minute which I guess will place a lock on each one and expecting the system would just automatically release them afterward, use to be fine before but for some reason now the list of locks keeps growing, so is there way to just release the lock after setting values in my globals  because I don't need them locked anyway?

 

 

 

Thanks

Product version: Ensemble 2018.1
Discussion (11)2
Log in or sign up to continue

Hi Rochdi,

If directly working with globals in a live system, I would strongly advise you to use the LOCK command to set and release locks. It is possible that if your process has not stopped, all the locks are still being retained.

Documentation: https://docs.intersystems.com/iris20232/csp/docbook/Doc.View.cls?KEY=RCO...

Consider using the following from the documentation:

  • LOCK +lockname applies a lock on the specified lock name(s) without unlocking any previous locks. This allows you to accumulate different locks, and allows you to apply incremental locks to the same lock.
  • LOCK -lockname performs an unlock operation on the specified lock name(s). Unlocking decrements the lock count for the specified lock name; when this lock count decrements to zero, the lock is released.

Additionally, using LOCK without arguments, will release all active locks in the namespace held by the current process.

Basically. The tcommiit will commit the current open transaction. Lock -^global (decremental lock ) is used to release the incremental lock( lock +^global) so everytime if you do incremental lock then you should decrement the lock) by using lock -^gbl syntax

Argumentless lock is release all the locks in the process. So this is not highly recommend in code. And incremental locks are highly recommend for use.

even deleting the lock from Terminal doesn't seems to work

Whatever you try to express doesn't make sense
Any kind of LOCK  is bound just to the job that executes it
there is just no "UNLOCK" from outside except job termination.

the locking job in your screenshot is 9908
but your terminal is job 10376  
expressed in a picture:
- you try to catch a fly in your room  that is flying somewhere outside the building

I recommend using two terminals to experiment with locking and unlocking various globals. By observing the lock table during this process, you'll gain a clearer understanding of lock behavior across different processes.

Next, consider what you're aiming to lock. In other words, identify what you're trying to safeguard and against which potential issues. For instance, is the variable "loc" unique? Could two processes obtain the same value for "loc"? Without seeing the preceding code, it's challenging to discern if "loc" was assigned manually or via `$Increment`. Remember, using `$Increment` eliminates the need for locks in most cases.

Also, reevaluate your decision to use transactions for a single global write. If your goal is transactional integrity, think about which additional global writes should be encompassed in that transaction. For example, if "obj" is defined just before this code with a `%Save()` method, then include that save in the same transaction. Otherwise, a system interruption between the two actions can lead to an unindexed object, compromising data integrity.

I strongly advise revisiting the documentation multiple times and actively experimenting with these concepts. While these techniques offer significant advantages, their efficacy diminishes if not executed properly.

The lock is belongs from different process(9908) and you're trying to terminate  via different process(10376) not is not possible. You can verify and terminate the 9908 in process  (System Operation>Process) if no longer required for prevent multiple locks set again and click remove all locks for process and remove it.

  • Use $test  special variable in your code to check the for success/failure lock. If lock is success it return 1 otherwise return 0 based on this result you can continue your logic flow.
  • Always use incremental lock with timeout (ex: lock +^test:0) 
LEARNING>w $test
0
LEARNING>lock +^test:0
 
LEARNING>w $test
1
LEARNING>

Sorry Ashok this code didn't work, my globals could set at all maybe because in the code it's locked before been set, will put some traces and see where it's stopping

tstart if staten["IUDX" { lock +^IudexNqlInByte(1):0 if $test{ set IudexNqlInByte(1,inc)=obj.%Id() lock -^IudexNqlInByte(1) } } else { lock +^ToshibaNQLIn(1):0 if $test { set ^ToshibaNQLIn(1,inc)=obj.%Id() lock -^ToshibaNQLIn(1) } } tcommit   

Hi Rochdi,

As mentioned, always ensure locks are explicitly released after use.

Reading between the lines a little, you might find these following points useful...

  • Locks don't actually "seal" a global node; they're advisory.
  • Any rogue process can still write to a locked global.
  • Another process is only deterred from writing to a global if it also attempts to obtain a lock and fails. The developer is responsible to implement this and handle failed locks in every location a write happens.
  • Without a timeout, a process can hang indefinitely due to a lock. You could argue its good practice to use a timeout.
  • If you implement a timeout, always verify the value of $test to ensure you've acquired the lock and not just timed out.
  • $Increment() is useful for creating sequenced ordinal ID's that are always unique, without the need for locks. This is true for high-concurrency solutions.

(If you're using locks only to make the key "inc" unique, then consider using $increment and forgo the locks.)