Several statements as one unit of work - #13
Merged
Merged
Conversation
Every statement already runs in a transaction of its own, so this is not what makes a write atomic. What it holds is the span: two statements are one unit, and the block rolls back when it raises, which is the failure worth writing it for since it is the one nobody wrote a handler for. `conn.transaction()` starts one and hands back a context manager that commits at the end of its block and rolls back when the block raised. It starts at the call rather than at the `with`, so a transaction that cannot start says so at the line that asked for one, and `commit()` and `rollback()` are there for a caller who would rather say when. A block whose transaction has already ended is left alone on the way out, and ending one twice is refused rather than ignored. `conn.in_transaction` answers which side of the block a program is on. The three statements underneath are the engine's own, so a read-only transaction refuses a write at the statement that writes and a second transaction is refused rather than nested. An appender is refused inside one, since its batches are commits of their own and a rollback does not take them back. The wrapper costs 5 microseconds for an empty transaction, so what it costs is what the engine charges, and on this machine that is more rather than less: 200 inserts cost 2.2 seconds each committing on its own and 3.3 seconds inside one transaction. The README says so.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every statement already runs in a transaction of its own, so this is not what makes a write atomic. What it holds is the span: two statements are one unit, and the block rolls back when it raises, which is the failure worth writing it for since it is the one nobody wrote a handler for.
conn.transaction()starts one and hands back a context manager. It starts at the call rather than at thewith, so a transaction that cannot start says so at the line that asked for one, andcommit()androllback()are there for a caller who would rather say when. A block whose transaction has already ended is left alone on the way out, which is what lets a program commit early and carry on, and ending one twice is refused rather than ignored, because the statements between the two are in neither of them.conn.in_transactionanswers which side of the block a program is on.The three statements underneath are the engine's own,
START TRANSACTION,COMMITandROLLBACK, and they all still work written out. So a read-only transaction refuses a write at the statement that writes rather than at the block that would have written, and a second transaction on the same connection is refused rather than nested, since a rollback of an inner one would have to invent an answer for what it undoes.An appender is refused inside a transaction, which is the one decision here that is this client's rather than the engine's. Its batches are commits of their own and a rollback does not take them back, so an appender opened in a block would promise a span it is not in. Load first, then transact.
The suite is nineteen tests: the commit path, the rollback path read back through a connection that was not there for it, explicit commit and rollback, the early commit, the double end, the read-only refusal, the nested refusal, the words written out, a failed statement leaving the transaction to its owner, the appender refusal, a connection closed with work uncommitted, a commit that cannot run raising out of the block, and the repr.
The wrapper costs 5 microseconds for an empty transaction, so what it costs is what the engine charges. On this machine that is more rather than less: 200
INSERTs cost 2.2 seconds each committing on its own and 3.3 seconds inside one transaction, and reads cost the same either way. The README says so rather than claiming the saving a transaction usually buys, and the v0 write path in the engine is where that number has to change.First of the three parts of the Python SDK v1 line of DX3 (tamnd/zu#169), with
register()replacement scans andzudb.aioto come.