diff --git a/doc/README.read_consistency.md b/doc/README.read_consistency.md index b2c2429cbe..52bcef203c 100644 --- a/doc/README.read_consistency.md +++ b/doc/README.read_consistency.md @@ -125,32 +125,53 @@ So, there are three kinds of read-committed transactions now: ### Update conflicts handling -When statement executed within read committed read consistency transaction its database view is +When statement executed within *read committed read consistency* transaction its database view is not changed (similar to snapshot transaction). Therefore it is useless to wait for commit of concurrent transaction in the hope to re-read new committed record version. On read, behavior is similar to read committed *record version* transaction - do not wait for active transaction and walk backversions chain looking for record version visible to the current snapshot. -When update conflict happens engine behavior is changed. If concurrent transaction is active, -engine waits (according to transaction lock timeout) and if concurrent transaction still not -committed, update conflict error is returned. If concurrent transaction is committed, engine -creates new snapshot and restart top-level statement execution. In both cases all work performed -up to the top-level statement is undone. +For *read committed read consistency* mode handling of update conflicts by the engine is changed +significantly. +When update conflict is detected the following is performed: +a) transaction isolation mode temporarily switched to the read committed *no record version mode* +b) engine put write lock on conflicted record +c) engine continue to evaluate remaining records of update\delete cursor and put write locks + on it too +d) when there is no more records to fetch, engine start to undo all actions performed since + top-level statement execution starts and put write locks on every updated\deleted record, + all inserted records are removed +e) then engine restores transaction isolation mode as read committed *read consistency*, creates + new statement-level snapshot and restart execution of top-level statement. -This is the same logic as user applications uses for update conflict handling usually, but it -is a bit more efficient as it excludes network roundtrips to\from client host. This restart -logic is not applied to the selectable stored procedures if update conflict happens after any -record returned to the client application. In this case *isc_update_conflict* error is returned. +Such algorithm allows to ensure that after restart already updated records remains locked, +will be visible to the new snapshot, and could be updated again with no further conflicts. +Also, because of read consistency mode, set of modified records remains consistent. -Note: by historical reasons isc_update_conflict reported as secondary error code with primary -error code isc_deadlock. +Notes: +- restart algorithm above is applied to the UPDATE, DELETE, SELECT WITH LOCK and MERGE + statements, with and without RETURNING clause, executing directly by user applicaiton or + as a part of some PSQL object (stored procedure\function, trigger, EXECUTE BLOCK, etc) +- if UPDATE\DELETE statement is positioned on some explicit cursor (WHERE CURRENT OF) then + engine skip step (c) above, i.e. not fetches and not put write locks on remaining records + of cursor +- if top-level statement is SELECT'able and update conflict happens after one or more records + was returned to the application, then update conflict error is reported as usual and restart + is not initiated +- restart is not initiated for statements in autonomous blocks +- after 10 attempts engine stop restarts and report update conflict +- by historical reasons isc_update_conflict reported as secondary error code with primary + error code isc_deadlock. -### No more precommitted transactions -*Read-committed read only* (RCRO) transactions currently marked as committed immediately when -transaction started. This is correct if read-committed transaction needs no database snapshot. -But it is not correct to mark RCRO transaction as committed as it can break statement-level -snapshot consistency. +### Precommitted transactions + +*Read-committed read only* transactions marked as committed immediately when transaction started. +This is correct if read-committed transaction needs no database snapshot. But it is not correct +to mark *read consistency read only* transaction as committed as it can break statement-level +snapshot consistency. Therefore *read consistency read only* transactions is not precommitted +on start. Other kinds of read committed read only transactions (*[no] record version*) works as +before and marked as committed when such transaction started. ### Support for new READ COMMITTED READ CONSISTENCY isolation level #### SQL syntax