ปัญหา
โปรแกรม COBOL-DB2 เปลี่ยนความยาวตัวแปรจาก PIC X(5) เป็น PIC X(8) แต่ ไม่มีการเปลี่ยนแปลง SQL โปรแกรมถูก Compile ใหม่ แต่ ไม่ได้ BIND PLAN/PACKAGE ใหม่
ผลลัพธ์: SQLCODE -818
THE PRECOMPILER-GENERATED TIMESTAMP x IN THE LOAD MODULE IS DIFFERENT FROM THE BIND TIMESTAMP y BUILT FROM THE DBRM z
สาเหตุ
- Pre-compile สร้าง DBRM (Database Request Module) และ Timestamp ไว้ใน Load Module
- Compile ใหม่ → Load Module ได้ Timestamp ใหม่
- ไม่ BIND → Package/DBRM ยังมี Timestamp เก่า
- ตอนรัน: DB2 เปรียบเทียบ Timestamp ทั้งสอง → ไม่ตรง → SQLCODE -818
Timeline การทำงาน COBOL-DB2
COBOL Source
│
├─ Pre-compile ──→ DBRM (SQL statements + Timestamp T1) ──→ BIND ──→ Package (Timestamp T1)
│
└─ Compile/Link ──→ Load Module (Timestamp T1)
Execution: Load Module (T1) vs Package (T1) → OK ✅
หลังแก้โค้ด (Non-SQL change):
│
├─ Pre-compile ──→ DBRM (Timestamp T2) ──→ BIND ──→ Package (Timestamp T2) ← ถ้า BIND
│
└─ Compile/Link ──→ Load Module (Timestamp T2)
Execution: Load Module (T2) vs Package (T1) → MISMATCH → SQLCODE -818 ❌
วิธีแก้: BIND ใหม่เสมอหลัง Compile
แม้ SQL ไม่เปลี่ยน ต้อง BIND ทุกครั้งที่ Compile ใหม่
ตัวเลือก LEVEL สำหรับโปรแกรมที่ SQL ไม่เปลี่ยน
ใช้ BIND option LEVEL เพื่อบอก DB2 ว่า SQL Layer ไม่เปลี่ยน — เร็วกว่าและลด Lock:
//BIND EXEC PGM=IKJEFT01 //STEPLIB DD DSN=DSN.TEST.LOADLIB,DISP=SHR //SYSOUT DD SYSOUT=* //SYSTSIN DD * DSN SYSTEM(TB3) BIND PLAN(PLANA) PKLIST(PACKA) LEVEL(abc123) <-- ใช้ Token แทน Timestamp ACQUIRE(ALLOCATE) ISOLATION(RS) /*
LEVEL Option
- ระบุ Consistency Token (String 1-8 ตัวอักษร) แทน Timestamp
- Pre-compile ด้วย
LEVEL(abc123)→ DBRM และ Load Module จะมี Token เดียวกัน - BIND ด้วย
LEVEL(abc123)→ Package ใช้ Token เดียวกัน - ตอนรัน: เปรียบเทียบ Token → Match เสมอ (ตราบใดที่ SQL ไม่เปลี่ยน)
ข้อดีของ LEVEL
- ไม่ต้อง BIND ทุกครั้งที่ Compile (Non-SQL change)
- ลด Catalog Lock contention
- เหมาะสำหรับโปรแกรม Stable SQL (Batch, Report)
ข้อควรระวัง
- หาก SQL เปลี่ยนจริง → ต้อง Pre-compile ใหม่ (Token ใหม่) และ BIND ใหม่
- Token ต้อง Unique ต่อ Program Version
- ไม่รองรับ Dynamic SQL