Considerations for using buffered inserts
Buffered inserts exhibit behaviors that can affect an application program. This behavior is caused by the asynchronous nature of the buffered inserts. Based on the values of the row's distribution key, each inserted row is placed in a buffer destined for the correct partition. These buffers are sent to their destination partitions as they become full, or an event causes them to be flushed. You must be aware of the following, and account for them when designing and coding the application:
- Certain error conditions for inserted rows are not reported when the INSERT statement is executed. They are reported later, when the first statement other than the INSERT (or INSERT to a different table) is executed, such as DELETE, UPDATE, COMMIT, or ROLLBACK. Any statement or API that closes the buffered insert statement can see the error report. Also, any invocation of the insert itself may see an error of a previously inserted row. Moreover, if a buffered insert error is reported by another statement, such as UPDATE or COMMIT, Db2® will not attempt to execute that statement.
- An error detected during the insertion of a group of rows causes
all the rows of that group to be backed out. A group of rows is defined
as all the rows inserted through executions of a buffered insert statement:
- From the beginning of the unit of work,
- Since the statement was prepared (if it is dynamic), or
- Since the previous execution of another updating statement. For a list of statements that close (or flush) a buffered insert, see the description of buffered inserts in partitioned database environments.
- An inserted row may not be immediately visible to SELECT statements issued after the INSERT by the same application program, if the SELECT is executed using a cursor.
A buffered INSERT statement is either open or closed. The first invocation of the statement opens the buffered INSERT, the row is added to the appropriate buffer, and control is returned to the application. Subsequent invocations add rows to the buffer, leaving the statement open. While the statement is open, buffers may be sent to their destination partitions, where the rows are inserted into the target table's partition. If any statement or API that closes a buffered insert is invoked while a buffered INSERT statement is open (including invocation of a different buffered INSERT statement), or if a PREPARE statement is issued against an open buffered INSERT statement, the open statement is closed before the new request is processed. If the buffered INSERT statement is closed, the remaining buffers are flushed. The rows are then sent to the target partitions and inserted. Only after all the buffers are sent and all the rows are inserted does the new request begin processing.
- If the error is a deadlock, the transaction is rolled back (including any changes made before the buffered insert section was opened).
- If the error is a unique key violation, the state of the database is the same as before the statement was opened. The transaction remains active, and any changes made before the statement was opened are not affected.
EXEC SQL UPDATE t1 SET COMMENT='about to start inserts';
DO UNTIL EOF OR SQLCODE < 0;
READ VALUE OF hv1 FROM A FILE;
EXEC SQL INSERT INTO t2 VALUES (:hv1);
IF 1000 INSERTS DONE, THEN DO
EXEC SQL INSERT INTO t3 VALUES ('another 1000 done');
RESET COUNTER;
END;
END;
EXEC SQL COMMIT;Suppose the file contains 8 000 values, but value 3 258 is not
legal (for example, a unique key violation). Each 1 000 inserts results
in the execution of another SQL statement, which then closes the INSERT
INTO t2 statement. During the fourth group of 1 000 inserts,
the error for value 3 258 will be detected. It may be detected after
the insertion of more values (not necessarily the next one). In this
situation, an error code is returned for the INSERT INTO t2 statement.
The error may also be detected when an insertion is attempted on
table t3, which closes the INSERT INTO t2 statement.
In this situation, the error code is returned for the INSERT
INTO t3 statement, even though the error applies to table t2.
Suppose, instead, that you have 3 900 rows to insert. Before being
told of the error on row number 3 258, the application may exit the
loop and attempt to issue a COMMIT. The unique-key-violation return
code will be issued for the COMMIT statement, and the COMMIT will
not be performed. If the application wants to COMMIT the 3 000 rows
that are in the database thus far (the last execution of EXEC
SQL INSERT INTO t3 ... ends the savepoint for those 3 000
rows), the COMMIT has to be reissued. Similar considerations
apply to ROLLBACK as well.
SQLCODE < 0 clause
from the THEN DO statement in the above example, the table could end
up containing an indeterminate number of rows.