DB2 Isolation Levels - Concurrency Crisis
Table of Contents
Interview Question
"Your online banking CICS application has a critical issue:
Symptom:
- Customers report seeing $0.00 balance during transfers
- Balance shows correct amount after refresh
- Happens during high-volume periods (month-end, paydays)
- Complaint rate: 200+ calls/day
Current Code:
EXEC SQL
SELECT ACCOUNT_BALANCE
INTO :WS-BALANCE
FROM ACCOUNTS
WHERE ACCOUNT_NUMBER = :WS-ACCT-NBR
END-EXEC.
* Display balance on screen
MOVE WS-BALANCE TO SCREEN-BALANCE
* User initiates transfer
EXEC SQL
UPDATE ACCOUNTS
SET ACCOUNT_BALANCE = ACCOUNT_BALANCE - :WS-TRANSFER-AMT
WHERE ACCOUNT_NUMBER = :WS-ACCT-NBR
END-EXEC.
Analysis shows:
- Transaction A reads balance ($5,000)
- Transaction B updates balance (withdrawal $500)
- Transaction B commits
- Transaction A displays $0 (invalid data)
Requirements:
- Fix the phantom read issue
- Maintain high concurrency (1000 TPS)
- No table-level locking (performance killer)
- Must work with existing CICS infrastructure
Which isolation level solves this? What's the trade-off?"
What This Tests
- Deep understanding of DB2 locking
- Concurrency control expertise
- Performance vs. consistency trade-offs
- Production problem-solving
Good Answer Should Include
1. Root Cause:
- Current isolation level: UR (Uncommitted Read) or no explicit isolation
- Allows dirty reads - reading data being modified by other transactions
- No row locking during SELECT
- High concurrency but inconsistent results
2. Solution:
Use CS (Cursor Stability) isolation level:
EXEC SQL
SELECT ACCOUNT_BALANCE
INTO :WS-BALANCE
FROM ACCOUNTS
WHERE ACCOUNT_NUMBER = :WS-ACCT-NBR
WITH CS
END-EXEC.
BIND PLAN(ACCTPLAN) ISOLATION(CS)
3. Isolation Level Comparison:
| Level | Locking Behavior | Phantom Reads | Performance | Use Case |
|---|---|---|---|---|
| UR | No locks | Yes | Highest | Read-only queries, reports |
| CS | Lock current row only | No | High | OLTP (BEST CHOICE) |
| RS | Lock all qualifying rows | No | Medium | Multi-row consistency |
| RR | Lock entire table | No | Low | Batch, critical updates |
4. Why CS is Optimal:
- Locks row being read - prevents dirty reads
- Releases lock after moving to next row - maintains concurrency
- Minimal lock contention - only one row locked at a time
- Supports 1000 TPS requirement - proven in high-volume environments
5. Additional Improvements:
* Add FOR UPDATE to ensure lock held for entire transaction
EXEC SQL
SELECT ACCOUNT_BALANCE
INTO :WS-BALANCE
FROM ACCOUNTS
WHERE ACCOUNT_NUMBER = :WS-ACCT-NBR
FOR UPDATE OF ACCOUNT_BALANCE
END-EXEC.
* Verify balance hasn't changed before update
EXEC SQL
UPDATE ACCOUNTS
SET ACCOUNT_BALANCE = ACCOUNT_BALANCE - :WS-TRANSFER-AMT
WHERE ACCOUNT_NUMBER = :WS-ACCT-NBR
AND ACCOUNT_BALANCE = :WS-ORIGINAL-BALANCE
END-EXEC.
IF SQLCODE NOT = 0
DISPLAY 'Balance changed. Please retry.'
END-IF.
6. Monitoring:
- Track deadlocks (SQLCODE -911, -913)
- Monitor lock wait times
- Implement retry logic for timeouts
Red Flags
- ❌ Suggests RR (overkill, kills performance)
- ❌ Doesn't understand dirty read concept
- ❌ Can't explain difference between CS and RS
- ❌ Ignores performance requirements (1000 TPS)
- ❌ Doesn't mention FOR UPDATE option
Follow-Up Questions
- "What if you need to read 100 accounts and ensure no changes during processing?"
- "How do you handle SQLCODE -911 (deadlock)?"
- "Why not use RR if consistency is critical?"
- "What's the lock escalation concern with RS?"
Difficulty Level
Senior
Relevant Roles
Database Specialist, CICS Developer, Performance Analyst