mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-27 04:54:21 +01:00
Currently, when MVCC is enabled, every transaction mode supports concurrent reads and writes, which makes it hard to adopt for existing applications that use `BEGIN DEFERRED` or `BEGIN IMMEDIATE`. Therefore, add support for `BEGIN CONCURRENT` transactions when MVCC is enabled. The transaction mode allows multiple concurrent read/write transactions that don't block each other, with conflicts resolved at commit time. Furthermore, implement the correct semantics for `BEGIN DEFERRED` and `BEGIN IMMEDIATE` by taking advantage of the pager level write lock when transaction upgrades to write. This means that now concurrent MVCC transactions are serialized against the legacy ones when needed. The implementation includes: - Parser support for CONCURRENT keyword in BEGIN statements - New Concurrent variant in TransactionMode to distinguish from regular read/write transactions - MVCC store tracking of exclusive transactions to support IMMEDIATE and EXCLUSIVE modes alongside CONCURRENT - Proper transaction state management for all transaction types in MVCC This enables better concurrency for applications that can handle optimistic concurrency control, while still supporting traditional SQLite transaction semantics via IMMEDIATE and EXCLUSIVE modes.
69 lines
2.1 KiB
Rust
69 lines
2.1 KiB
Rust
use crate::schema::Schema;
|
|
use crate::translate::{emitter::TransactionMode, ProgramBuilder, ProgramBuilderOpts};
|
|
use crate::vdbe::insn::Insn;
|
|
use crate::Result;
|
|
use turso_parser::ast::{Name, TransactionType};
|
|
|
|
pub fn translate_tx_begin(
|
|
tx_type: Option<TransactionType>,
|
|
_tx_name: Option<Name>,
|
|
schema: &Schema,
|
|
mut program: ProgramBuilder,
|
|
) -> Result<ProgramBuilder> {
|
|
program.extend(&ProgramBuilderOpts {
|
|
num_cursors: 0,
|
|
approx_num_insns: 0,
|
|
approx_num_labels: 0,
|
|
});
|
|
let tx_type = tx_type.unwrap_or(TransactionType::Deferred);
|
|
match tx_type {
|
|
TransactionType::Deferred => {
|
|
program.emit_insn(Insn::AutoCommit {
|
|
auto_commit: false,
|
|
rollback: false,
|
|
});
|
|
}
|
|
TransactionType::Immediate | TransactionType::Exclusive => {
|
|
program.emit_insn(Insn::Transaction {
|
|
db: 0,
|
|
tx_mode: TransactionMode::Write,
|
|
schema_cookie: schema.schema_version,
|
|
});
|
|
// TODO: Emit transaction instruction on temporary tables when we support them.
|
|
program.emit_insn(Insn::AutoCommit {
|
|
auto_commit: false,
|
|
rollback: false,
|
|
});
|
|
}
|
|
TransactionType::Concurrent => {
|
|
program.emit_insn(Insn::Transaction {
|
|
db: 0,
|
|
tx_mode: TransactionMode::Concurrent,
|
|
schema_cookie: schema.schema_version,
|
|
});
|
|
// TODO: Emit transaction instruction on temporary tables when we support them.
|
|
program.emit_insn(Insn::AutoCommit {
|
|
auto_commit: false,
|
|
rollback: false,
|
|
});
|
|
}
|
|
}
|
|
Ok(program)
|
|
}
|
|
|
|
pub fn translate_tx_commit(
|
|
_tx_name: Option<Name>,
|
|
mut program: ProgramBuilder,
|
|
) -> Result<ProgramBuilder> {
|
|
program.extend(&ProgramBuilderOpts {
|
|
num_cursors: 0,
|
|
approx_num_insns: 0,
|
|
approx_num_labels: 0,
|
|
});
|
|
program.emit_insn(Insn::AutoCommit {
|
|
auto_commit: true,
|
|
rollback: false,
|
|
});
|
|
Ok(program)
|
|
}
|