What it means
Each CICS TRANSACTION definition can have a deadlock timeout, the DTIMOUT attribute. When a task with a nonzero DTIMOUT stays suspended for longer than that, CICS assumes it is stuck and ends it with AKCS. This stops tasks that are waiting on each other from hanging forever. DTIMOUT only takes effect when the transaction is also defined with SPURGE(YES). With DTIMOUT(NO) or SPURGE(NO), the task can wait indefinitely and never gets AKCS. Waits for terminal input aren't covered by DTIMOUT at all.
The name says deadlock, but most AKCS abends aren't true deadlocks. The task is usually waiting behind another task that holds a record or an enqueue for too long, or waiting for storage when the region is short of it. The timer counts elapsed time. So if CICS stops running for a while, for example while a system dump is being taken, waiting tasks can pass their limit too.
Common causes
- Another task holds a lock on a VSAM record this task needs. A program that reads a record for update and then waits for something slow, or holds the lock across a terminal conversation, makes every other task that wants that record wait.
- Many transactions serialize on one resource, such as a single control record or an EXEC CICS ENQ on a counter, and one of them holds it for too long.
- A real deadlock. Task A holds one resource and wants a second, while task B holds the second and wants the first.
- The region is short on storage, or temporary storage is full, and tasks are waiting for space.
- The task is waiting for a session to another system (ALLOCATE) or for data with RETRIEVE WAIT, and the other side is slow or unavailable.
- CICS itself paused, for example during a system dump, and tasks that were already waiting ran past their timeout.
How to find the problem
- The terminal message
DFHAC2206names the transaction. AKCS doesn't always produce a transaction dump. Whether it does depends on the dump table entry for AKCS, which the CICS systems programmers control. - While the problem is happening, run
CEMT INQUIRE TASK. Suspended tasks show the type and name of the resource each one is waiting for, in the HTYPE and HVALUE fields. That points straight at the record, enqueue or storage involved. - Use
CEMT INQUIRE UOWENQto see which task owns an enqueue and which tasks are waiting for it. The owner is the one to look at. - Check the region's log for short-on-storage messages from the same time. If they are there, the waits are a region capacity problem, not a program design problem.
- Monitoring tools such as CICS Explorer or OMEGAMON show the same wait information live, and often keep history you can look back through.
How to fix it
- Hold update locks for as short a time as possible. Read for update, rewrite and reach a syncpoint quickly. Never hold a lock while the program waits for the terminal user. Pseudo-conversational design avoids that.
- Make every program that needs more than one resource take them in the same order. Two programs that lock the same records in opposite orders will deadlock sooner or later.
- Reduce serialization on single control records. Keeping a counter in one record that every transaction updates is a common cause of AKCS at busy times.
- If the waits come from short-on-storage or full temporary storage, the CICS systems programmers need to look at the storage limits and at what is using the space.
- An occasional AKCS at peak times can be normal, and rerunning the transaction usually works. The same transaction getting AKCS again and again points to a design problem. Raising DTIMOUT only makes users wait longer before the same failure.
- Don't remove DTIMOUT or set SPURGE(NO) to make the abend go away. Stuck tasks would then wait with no limit and tie up the resources they hold.
What it looks like
DFHAC2206 16:48:52 CICSPRD1 Transaction ACC2 failed with abend AKCS. Updates to local recoverable resources backed out.