Skip to main content

MySql

Struct MySql 

Source
pub struct MySql;
Expand description

MySQL and MariaDB: backtick-quoted names, ? placeholders, rows claimed with FOR UPDATE SKIP LOCKED.

It builds the statements of the row lock form (RowLock), of the lease form (Lease), of the advisory lock form (Advisory), and the insert, for MySQL 8.0.1 and MariaDB 10.6 or later, the first versions that skip locked rows; check_server refuses an older server for a table in any form. A lease claim selects the claimable rows, then stamps each one with its lease (stamp) before its transaction commits. A dead letter into a table copies the row, then deletes it, in one transaction. Every name is quoted, so a name keeps its case and may hold any character; a name over 64 characters, which MySQL refuses, is refused before it reaches the server. A table on the database’s clock reads UTC_TIMESTAMP(6). fetch is refused, so a claim of the service’s own brings a fetch of its own.

A claim’s transaction opens at READ COMMITTED in both forms (begin for a table that names no level, begin_lease_claim): under the server’s default REPEATABLE READ a locking read also locks the gaps between the rows it scans, so a claim held for a handler would block every insert into the table until it ends. A server whose binary log records statements (binlog_format = STATEMENT) refuses writes in such a transaction; the row and mixed formats accept them. A row lock table that names a level opens its claims at it, any of the four, READ UNCOMMITTED included; REPEATABLE READ and SERIALIZABLE bring the gap locks back.

In the advisory lock form a row’s key is the text CONCAT_WS renders from the key’s parts, a column without a value skipped. A session lock (GET_LOCK) holds the row, named by the table’s database, a dot and the key (app.jobs-7): the server names its locks server-wide, and the database keeps the locks of two databases on one server apart. The server takes a lock name of 1 to 64 characters, so a longer name is locked by its SHA-256, 64 characters of hex: the claim selects the name it locks. The claim leaves out the names IS_USED_LOCK reports in use. An update returns no rows here, so the take counts the attempt, then reads the row.

In a table with FIFO groups a claim’s transaction takes its group (fifo_guard) with a locking read of the group’s unfinished rows that skips the rows other transactions hold: the group is the claim’s when the read took all of them. The rows stay locked until the transaction ends, in the row lock form until the delivery settles, and a write to one of them from elsewhere waits that long. Each claim reads every unfinished row of its group, and the whole table where the group’s column has no index. A row lock table with FIFO groups claims below SERIALIZABLE: every read of a SERIALIZABLE transaction locks the rows it reads, so the guard would wait for the group’s row in work, and it refuses such a table with StatementError::FifoAtSerializable.

§Examples

A subscription asks MySQL for the statements of its table, as ruststream-sqlx does when the subscription starts:

use ruststream_sqlx_dialect::{
    ClaimShape, Column, Form, Lease, MySql, Statement, StatementError, TableSpec,
};

// The jobs table as `#[derive(Inbox)]` describes it, with a `#[field(locked_until)]` field.
const JOBS: TableSpec<'static> = TableSpec::new(
    "jobs",
    Column::new("job_id"),
    Form::Lease(Column::new("locked_until")),
);

// What a subscription to a lease table prepares: the claim, and the stamp where the claim
// only selects its rows.
fn lease_statements(
    dialect: &impl Lease,
    spec: &TableSpec<'_>,
) -> Result<Vec<Statement>, StatementError> {
    let mut statements = vec![dialect.lease_claim(spec, ClaimShape::Rows)?];
    if !dialect.claim_writes_lease() {
        statements.push(dialect.stamp(spec)?);
    }
    Ok(statements)
}

fn main() -> Result<(), StatementError> {
    // MySQL's claim selects the rows, and each row it took is stamped with its lease before
    // the claim's transaction commits.
    let statements = lease_statements(&MySql, &JOBS)?;
    assert_eq!(statements.len(), 2);
    Ok(())
}

Trait Implementations§

Source§

impl Advisory for MySql

Source§

fn advisory_claim( &self, spec: &TableSpec<'_>, ) -> Result<Statement, StatementError>

The candidates: up to Param::Limit claimable rows of the subscription’s group in claim order, two columns each, the id and the lock key as text (named __lock). It takes no lock and writes nothing; where the database can tell, it leaves out the rows whose key another session holds. Read more
Source§

fn lock(&self) -> Option<Statement>

Tries the lock on Param::Key for the session, without waiting: one row whose first column is a 64-bit integer, nonzero when the lock was taken. None when the process keeps the locks. Read more
Source§

fn unlock(&self) -> Option<Statement>

Releases the lock on Param::Key: one row whose first column is a 64-bit integer, nonzero when the session held it. None when the process keeps the locks. Read more
Source§

fn take( &self, spec: &TableSpec<'_>, shape: ClaimShape, ) -> Result<Vec<Statement>, StatementError>

The statements that take a candidate whose lock the session holds: they count its attempt where the table has one and read the row again in shape, as it was before the count, only while it is still claimable. The last returns the row, or none when the row is gone or no longer claimable; a first statement, where there are two, counts the attempt and changes no row in that case. Read more
Source§

impl Clone for MySql

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for MySql

Source§

impl Debug for MySql

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for MySql

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Dialect for MySql

Source§

fn name(&self) -> &'static str

The dialect’s name, for messages. Read more
Source§

fn quote_into(&self, ident: &str, out: &mut String)

Appends ident to out, quoted as a name of this database. Read more
Source§

fn placeholder_into(&self, _: NonZeroUsize, out: &mut String)

Appends the placeholder of parameter number index (counted from 1) to out. Read more
Source§

fn fetch(&self, _: &TableSpec<'_>) -> Result<Statement, StatementError>

The statement that reads the rows of claimed ids, bound as one list. Read more
Source§

fn ack(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>

The statement that acknowledges a row: it deletes the row, or sets processed_at when the table has that column. Read more
Source§

fn retry( &self, spec: &TableSpec<'_>, ) -> Result<Option<Statement>, StatementError>

The statement that releases a row for another attempt at once, or None when releasing the row needs no statement. Read more
Source§

fn retry_after(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>

The statement that releases a row for another attempt after a delay, bound as Param::RetryAfter. Read more
Source§

fn discard(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>

The statement that drops a row: it deletes the row, or sets processed_at when the table has that column. Read more
Source§

fn dead_letter_group( &self, spec: &TableSpec<'_>, ) -> Result<Statement, StatementError>

The statement that moves a row whose attempts are spent to another group, bound as Param::Destination. Read more
Source§

fn dead_letter_table( &self, spec: &TableSpec<'_>, target: TableName<'_>, ) -> Result<Vec<Statement>, StatementError>

The statements that move a row whose attempts are spent to target, a table with the same columns; they run in one transaction. Read more
Source§

fn insert(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>

The statement that inserts a row: every column the database does not fill, in the order of TableSpec::columns, each bound as Param::Column. Read more
Source§

fn server_version(&self) -> Option<&'static str>

The query that reads the server’s version as one text column, or None when the dialect’s statements run on every version of its server. Read more
Source§

fn check_server( &self, _: &TableSpec<'_>, version: &str, ) -> Result<(), StatementError>

Refuses a server older than the statements of spec need; version is what the server_version query returned. Read more
Source§

fn begin( &self, opening: Opening, ) -> Result<Option<&'static str>, StatementError>

The statement that opens a transaction at opening in place of BEGIN, or None when BEGIN opens it. Read more
Source§

fn fifo_guard( &self, spec: &TableSpec<'_>, ) -> Result<Option<Statement>, StatementError>

The statement a claim of a table with FIFO groups runs first in its transaction, to take the subscription’s group for it; None for a table without FIFO groups, or a dialect that takes no group. Read more
Source§

fn savepoint(&self) -> &'static str

The statement that sets the savepoint after a claim, inside the claim’s transaction: what a handler writes after it can be discarded while the claim’s own work stays. Read more
Source§

fn rollback_to_savepoint(&self) -> &'static str

The statement that discards what the transaction did after savepoint, and keeps the transaction open. Read more
Source§

impl Eq for MySql

Source§

impl Hash for MySql

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Lease for MySql

Source§

fn lease_claim( &self, spec: &TableSpec<'_>, shape: ClaimShape, ) -> Result<Statement, StatementError>

The statement that claims up to Param::Limit rows of the subscription’s group, in claim order, among the rows whose lease ended by Param::LeaseNow. Read more
Source§

fn extend(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>

The statement that extends a delivery’s lease: it writes the new expiry (Param::Lease) while the row still holds the delivery’s token (Param::Held), so a handler that runs longer than one lease keeps its row. Read more
Source§

fn stamp(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>

The statement that leases one claimed row: it writes the expiry (Param::Lease) and counts the attempt, while no lease holds the row at Param::LeaseNow. Read more
Source§

fn claim_writes_lease(&self) -> bool

Whether the lease claim writes the lease itself. A dialect whose lease claim only selects the rows answers false, and the claim’s transaction then runs stamp for each claimed row before it commits. Read more
Source§

fn begin_lease_claim(&self) -> Option<&'static str>

The statement that opens the transaction of a claim that only selects its rows, in place of BEGIN, or None when BEGIN opens it. Read more
Source§

fn claim_counts_attempt(&self, spec: &TableSpec<'_>) -> bool

Whether the rows the lease claim of spec returns carry the attempt the claim counted. A dialect whose claim returns the rows as they were before answers false; where it answers true, a delivery reports one less than its row carries. Read more
Source§

impl Opens<ReadCommitted> for MySql

Source§

impl Opens<ReadUncommitted> for MySql

Source§

impl Opens<RepeatableRead> for MySql

Source§

impl Opens<Serializable> for MySql

Source§

impl OutboxDialect for MySql

Source§

fn outbox_fetch( &self, spec: &TableSpec<'_>, ) -> Result<Statement, StatementError>

The statement that reads the record Param::Id names while it is unprocessed, with every column: what the consumer of a tracked message takes into work. Read more
Source§

fn outbox_mark(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>

The statement that marks the record Param::Id names processed: it sets processed_at to now, or deletes the record in a table without that column. Read more
Source§

fn outbox_recover( &self, spec: &TableSpec<'_>, ) -> Result<Statement, StatementError>

The statement that reads the unprocessed records published under the name Param::Group binds, with every column: what the republish at startup sends again. Read more
Source§

impl PartialEq for MySql

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl RowLock for MySql

Source§

fn lock_claim( &self, spec: &TableSpec<'_>, shape: ClaimShape, ) -> Result<Statement, StatementError>

The statement that claims up to Param::Limit rows of the subscription’s group, in claim order, and locks them until the claim’s transaction ends. Read more
Source§

impl StructuralPartialEq for MySql

Auto Trait Implementations§

§

impl Freeze for MySql

§

impl RefUnwindSafe for MySql

§

impl Send for MySql

§

impl Sync for MySql

§

impl Unpin for MySql

§

impl UnsafeUnpin for MySql

§

impl UnwindSafe for MySql

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<D> Opens<()> for D
where D: Dialect,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.