Fast SQL that holds locks for minutes still fails in production. DB2 concurrency tuning is about commit frequency, thread reuse, connection pooling, and the lock waits that show up as deadlocks and timeouts. This page connects those knobs so beginners can see why a “read-only” DDF program that never commits can exhaust DBATs.
Locks and claims last until COMMIT or ROLLBACK (with exceptions: WITH HOLD cursors, LOCK TABLE, some LOB locators). Isolation (CS, RS, RR, UR) and lock size (row, page, table, table space) decide how many other threads you block. Accounting class 3 lock wait is the metric; SQLCODE -911 / -913 is the user-facing failure.
| Knob | Effect |
|---|---|
| Commit frequency | Releases locks, claims, and (DDF) allows pooling |
| Thread reuse / pooling | Cuts thread create CPU; can extend lock duration if DEALLOCATE |
| Lock size / isolation | Row vs page vs table space; CS vs RR vs RS |
| Access path | Scans take coarser locks and hold them longer |
| Timeout / deadlock ZPARMs | How long you wait and how often IRLM looks for cycles |
OLTP: commit once per business transaction. Nested SQL in a stored procedure still belongs to the caller’s unit of work unless you designed autonomous work.
Batch: commit every N rows (or every N minutes of work) so:
Too rare: timeouts, deadlock victims, huge rollback. Too often: commit-path CPU, extra log force, and slower elapsed. Tune N with Accounting lock wait versus CPU, not with superstition.
Distributed applications must commit even when they only SELECT. Otherwise the DBAT looks in-flight forever, hits IDTHTOIN idle timeout, or sits on MAXDBAT until the subsystem wheezes.
1234-- Batch pattern (host program issues COMMIT every 500 rows) UPDATE HR.EMPLOYEE SET BONUS = BONUS * 1.02 WHERE EMPNO = :HV-EMP;
A protected thread (CICS DB2ENTRY THREADLimit / PROTECT) stays allocated across transactions. Bind with RELEASE(DEALLOCATE) so packages stay in the EDM until the thread goes away—less allocation CPU, longer-lived parent locks. Use it for high-rate, short transactions. Do not combine it with transactions that never commit.
With CMTSTAT=INACTIVE (recommended), a clean commit sends the DBAT back to the pool and the connection can go inactive. The next transaction on that connection (or another) reuses a pooled DBAT. POOLINAC is how long an unused pooled DBAT lives (default often 120 seconds). Low reuse rates (< 95%) often mean POOLINAC is short or commits are not clean.
High-performance DBATs form when the DBAT runs a package bound RELEASE(DEALLOCATE). The DBAT stays glued to that connection across commits until a reuse limit (on the order of hundreds of transactions). CPU savings can be 10%+ on skinny SQL. Costs: memory growth, locks held across commits, harder to REBIND/DDL. Target chatty clients that commit hundreds of times per connection with steady arrival rate—not connect-once-a-day reports. MODIFY DDF PKGREL(COMMIT) is the emergency “stop HP DBATs” switch.
Pooling fails when WITH HOLD cursors stay open, declared temp tables are not dropped, KEEPDYNAMIC keeps state, or there is no commit. Statistics and IFCID 411/412 style reports help find “rogue” applications that never go inactive.
Application servers pool connections (sockets). Db2 pools threads (DBATs) separately. Limits:
A huge client pool of idle connections still counts against CONDBAT. Idle active threads count against MAXDBAT and IDTHTOIN. Profile tables (DSN_PROFILE_TABLE) can set connection and idle-thread limits per IP, authid, or application name without changing global ZPARMs.
Contention is time in class 3 lock/latch wait, plus page latch, drain, and in data sharing global contention / notify messages. Causes:
NUMLKTS / NUMLKUS and LOCKMAX control escalation to a bigger lock. Escalation reduces lock-table memory and can explode contention. Track escalations on Accounting; if they spike, commit more often or lock fewer rows (better access path), do not only raise the limit.
DEADLOK is how often IRLM searches for cycles. IRLMRWT (and CURRENT LOCK TIMEOUT) is how long a waiter waits before -911/-913. Deadlock victims and timeout counts belong on your weekly report.
Raising IRLMRWT from 30 to 600 seconds makes users wait ten minutes instead of failing fast. Prefer failing fast plus shorter commits unless you have a measured batch that needs a longer wait for a nightly exclusive.
A lock is borrowing a crayon. Commit is putting the crayon back so the next kid can use it. If you color for an hour without putting it back, everyone else waits (timeout) or two kids each hold a crayon the other needs (deadlock). Thread reuse is keeping the same desk for the next coloring session so you do not rebuild the desk every time. Connection pooling is the line of kids already in the classroom. High-performance DBATs are taping the crayon to one kid’s wrist for 200 pictures—faster for that kid, annoying for everyone who needed that color.
1. Why does even a read-only DDF transaction need a commit?
2. What does CMTSTAT=INACTIVE do for DDF?
3. How do high-performance DBATs get created?
4. What is the usual first fix for lock timeouts (-911 / -913)?
5. CICS thread reuse is most like which bind option?