I've only been writing DB2 procedures for a few days, but trying to do a "batch delete" on a given table. My expected logic is:
- to open a cursor
- walk through it until EOF
- issue a DELETE on each iteration
For sake of simplifying this question, assume I only want to issue a single COMMIT (of all DELETEs), after the WHILE loop is completed (ie. once cursor reaches EOF). So given the code sample below:
CREATE TABLE tableA (colA INTEGER, ...) CREATE PROCEDURE "SCHEMA"."PURGE_PROC" (IN batchSize INTEGER) LANGUAGE SQL SPECIFIC SQL140207163731500 BEGIN DECLARE tempID INTEGER; DECLARE eof_bool INTEGER DEFAULT 0; DECLARE sqlString VARCHAR(1000); DECLARE sqlStmt STATEMENT; DECLARE myCurs CURSOR WITH HOLD FOR sqlStmt; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET eof_bool = 1; SET sqlString = 'select colA from TableA'; PREPARE sqlStmt FROM sqlString; OPEN myCurs; FETCH myCurs INTO tempID; WHILE (eof_bool = 0) DO DELETE FROM TableA where colA = tempID; FETCH myCurs INTO tempID; END WHILE; COMMIT; CLOSE myCurs; END
Note: In my real scenario:
- I am not deleting all records from the table, just certain ones based on some additional criteria; and
- I plan to perform a COMMIT every N# iterations of the WHILE loop (say 500 or 1000), not the entire mess like above; and
- I plan to DELETE against multiple tables, not just this one;
But again, to simplify, I tested the above code, and what I'm seeing is that the DELETEs seem to be getting committed 1-by-1. I base this on the following test:
- I pre-load the table with (say 50k) records;
- then run the purge storedProc which takes ~60 secs to run;
- during this time, from another sql client, I continuously "SELECT COUNT(*) FROM tableA" and see count reducing incrementally.
If all DELETEs were committed at once, I would expect to see the record count(*) only drop from to 0 at the end of the ~60 seconds. That is what I see with comparable SPs written for Oracle or SQLServer.
This is DB2 v9.5 on Win2003.
Any ideas what I'm missing?
You are missing the difference in concurrency control implementation between the different database engines. In an Oracle database another session would see data that have been committed prior to the beginning of its transaction, that is, it would not see any deletes until the first session commits.
In DB2, depending on the server configuration parameters (e.g.
DB2_SKIPDELETED) and/or the second session isolation level (e.g. uncommitted read) it can in fact see (or not see) data affected by in-flight transactions.
If your business logic requires different transaction isolation, speak with your DBA.