Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/launchbadge/sqlx/llms.txt

Use this file to discover all available pages before exploring further.

SQLx’s MySQL driver is written in pure Rust and speaks the MySQL client/server protocol directly. It supports TLS, the full range of MySQL built-in types, JSON columns, and works with both MySQL (5.7+) and MariaDB (10.2+). The driver is runtime-agnostic and can be used with tokio or async-std.

Feature flag

Enable the driver by adding the mysql feature to your Cargo.toml. You must also choose a runtime and, optionally, a TLS backend.
[dependencies]
# tokio + rustls (recommended)
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls-ring-webpki", "mysql"] }

# tokio + native-tls
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-native-tls", "mysql"] }

# async-std, no TLS
sqlx = { version = "0.8", features = ["runtime-async-std", "mysql"] }
RSA password authentication (caching_sha2_password / sha256_password) without TLS requires the separate mysql-rsa feature. Enable it only if you must connect without TLS to a server that requires RSA auth. Prefer TLS instead.
sqlx = { version = "0.8", features = ["runtime-tokio", "mysql-rsa"] }

Connecting

Connection URL

mysql://[user[:password]@][host][:port]/[database][?param=value]
use sqlx::mysql::MySqlPool;

let pool = MySqlPool::connect("mysql://root:password@localhost/mydb").await?;

MySqlConnectOptions

For programmatic configuration, use MySqlConnectOptions:
use sqlx::mysql::{MySqlConnectOptions, MySqlSslMode, MySqlPoolOptions};

let opts = MySqlConnectOptions::new()
    .host("localhost")
    .port(3306)
    .username("root")
    .password("secret")
    .database("mydb")
    .ssl_mode(MySqlSslMode::Required);

let pool = MySqlPoolOptions::new()
    .max_connections(10)
    .connect_with(opts)
    .await?;
You can also parse a URL string and then override individual fields:
use sqlx::mysql::MySqlConnectOptions;

let mut opts: MySqlConnectOptions = "mysql://root:password@localhost/mydb".parse()?;
opts = opts.charset("utf8mb4");

Key options

OptionDefaultDescription
hostlocalhostHostname or Unix socket path
port3306TCP port
usernamerootLogin user
passwordNonePassword
databaseNoneTarget database
ssl_modePreferredTLS negotiation mode (see below)
charsetutf8mb4Connection character set
collationDerived from charsetConnection collation
timezone+00:00Session timezone (set to None to use server default)
statement_cache_capacity100LRU prepared-statement cache size per connection

TLS and MySqlSslMode

MySqlSslMode controls TLS negotiation. Pass it to .ssl_mode() on MySqlConnectOptions or set ssl-mode= in the URL.
VariantBehaviour
DisabledNever use TLS
PreferredTry TLS first; fall back to plain (default)
RequiredRequire TLS; do not verify the server certificate
VerifyCaRequire TLS; verify the server certificate is signed by a trusted CA
VerifyIdentityLike VerifyCa, plus hostname verification
use sqlx::mysql::{MySqlConnectOptions, MySqlSslMode};

let opts = MySqlConnectOptions::new()
    .ssl_mode(MySqlSslMode::VerifyCa)
    .ssl_ca("./ca.crt")
    .ssl_client_cert("./client.crt")
    .ssl_client_key("./client.key");
Using rustls requires TLS 1.2 or later. MySQL has supported TLS 1.2 since version 5.6.46. If you see HandshakeFailure, switch to the tls-native-tls feature for broader version support.

Connection pooling

MySqlPool (an alias for Pool<MySql>) manages a pool of connections.
use sqlx::MySqlPool;

let pool = MySqlPool::connect("mysql://root:password@localhost/mydb").await?;

Querying

MySQL uses ? as the bind parameter placeholder (unlike PostgreSQL’s $1):
// Low-level query
let row = sqlx::query("SELECT id, name FROM users WHERE email = ?")
    .bind("user@example.com")
    .fetch_one(&pool)
    .await?;

// Typed query with FromRow derive
#[derive(sqlx::FromRow)]
struct User {
    id: i64,
    name: String,
}

let user = sqlx::query_as::<_, User>(
    "SELECT id, name FROM users WHERE email = ?"
)
.bind("user@example.com")
.fetch_optional(&pool)
.await?;

// Compile-time checked (DATABASE_URL must be a MySQL/MariaDB URL)
let users = sqlx::query!(
    "SELECT id, name FROM users WHERE active = ?",
    true
)
.fetch_all(&pool)
.await?;

JSON support

Enable the json feature to map JSON columns to serde_json::Value:
sqlx = { version = "0.8", features = ["runtime-tokio", "mysql", "json"] }
use serde_json::Value;

let row: (Value,) = sqlx::query_as(
    "SELECT data FROM events WHERE id = ?"
)
.bind(42_i64)
.fetch_one(&pool)
.await?;

Type mapping

MySQL / MariaDB typeRust type
TINYINT(1) / BOOLbool
TINYINTi8
SMALLINTi16
INT / INTEGERi32
BIGINTi64
TINYINT UNSIGNEDu8
SMALLINT UNSIGNEDu16
INT UNSIGNEDu32
BIGINT UNSIGNEDu64
FLOATf32
DOUBLEf64
VARCHAR / TEXT / CHARString / &str
VARBINARY / BLOB / BINARYVec<u8> / &[u8]
JSONserde_json::Value (feature: json)
DECIMAL / NUMERICbigdecimal::BigDecimal (feature: bigdecimal)
DATETIMEchrono::NaiveDateTime (feature: chrono)
DATEchrono::NaiveDate (feature: chrono)
TIMEchrono::NaiveTime (feature: chrono)
TIMESTAMPchrono::DateTime<Utc> (feature: chrono)
UUID (as CHAR(36))uuid::Uuid (feature: uuid)
TIMESTAMP columns are not encoded with their UTC offset in the MySQL protocol. SQLx sets the session timezone to UTC (+00:00) by default. Changing .timezone() on MySqlConnectOptions without care can cause unexpected skew when encoding and decoding DateTime<Utc> values.

MariaDB compatibility

The MySQL driver is compatible with MariaDB 10.2 and later. MariaDB’s wire protocol is a fork of MySQL’s, and most features work transparently. A few notes:
  • MariaDB uses its own authentication plugins. If you encounter auth errors, ensure your server version is in SQLx’s supported range (check the CI configuration for tested versions).
  • The NO_ENGINE_SUBSTITUTION SQL mode is enabled by default. Disable it with .no_engine_substitution(false) if your MariaDB instance does not support it.
  • For sql_mode details, see the MariaDB documentation.

Build docs developers (and LLMs) love