faz
Databases

MySQL

Connect faz to a MySQL or MariaDB database. SQL queries, full DML support, schema discovery via information_schema.

faz's MySQL connector works against both MySQL and MariaDB (the wire protocol and information_schema layout are compatible). It speaks plain SQL gated by your permissions: block.

Default portQuery languageWrite supportSchema discoveryDriver
3306SQLYes (RBAC-gated)information_schemapymysql

Quick example

faz.yaml
databases:
  - name: <database>          # used as --database <database> in queries
    type: mysql
    host: localhost
    port: 3306
    database: <db-name>       # the actual MySQL database on the host
    username: <username>
    password: <password>

permissions:
  - database: <database>      # must match `name:` above
    access: R
    # access codes:
    # R    read only           — SELECT, EXPLAIN
    # W    write only          — INSERT, UPDATE, DELETE (no SELECT)
    # RW   read + write
    # RA   read + append       — SELECT, EXPLAIN, INSERT
    # RWA  read + write, no DELETE
    # A    admin (incl. DDL)

See Permissions for the full model, per-table overrides, and the operation matrix.

faz query "SELECT * FROM <table> LIMIT 5" --database <database> --table <table>
uv run faz query "SELECT * FROM <table> LIMIT 5" --database <database> --table <table>
python -m faz query "SELECT * FROM <table> LIMIT 5" --database <database> --table <table>

Configuration

FieldTypeDefaultNotes
hoststringlocalhostMySQL host or IP.
portinteger3306MySQL port.
databasestring""Database name. Required.
usernamestring""MySQL user.
passwordstring""Password. Env-var interpolation isn't yet implemented — see Secrets.
sslbooleanfalseWhen true, enables TLS via pymysql's ssl argument.
extramapping{}Reserved.

Unlike Postgres, the MySQL connector opens a fresh connection per operation — there's no built-in pool. For high-traffic deployments, run faz behind a connection-multiplexing proxy (ProxySQL, MaxScale).

Capabilities

  • Full SQL — SELECT, INSERT, UPDATE, DELETE, JOINs, CTEs (MySQL 8+), subqueries.
  • DDL (CREATE, ALTER, DROP, TRUNCATE) — only when the policy grants A.
  • Schema discovery via information_schema.TABLES and information_schema.COLUMNS.
  • Cardinality stats via information_schema.STATISTICS (index cardinality used as a row-count estimate).
  • Works against MariaDB without configuration changes.

Limitations

  • Stacked statements are blocked at the connector level. A query string with more than one top-level statement separated by ; is rejected before it reaches MySQL — defense-in-depth against stacked-query injection. Even if RBAC would allow each statement individually, the connector refuses to send the combined string. Only literal ;-separated stacking counts; complex single statements pass through fine.

    Blocked — two top-level statements separated by ;:

    SELECT * FROM <table-1>; DELETE FROM <table-2>;

    Allowed — single complex statements. RBAC checks every table they touch:

    -- UNION across two SELECTs
    SELECT <col> FROM <table-1>
    UNION ALL
    SELECT <col> FROM <table-2>;
    
    -- Subquery in FROM
    SELECT * FROM (SELECT * FROM <table> WHERE <condition>) sub;
    
    -- CTE / WITH clause (MySQL 8+)
    WITH recent AS (SELECT * FROM <table>)
    SELECT * FROM recent JOIN <other-table> USING (<key>);
    
    -- Insert-from-select — one statement, RBAC checks BOTH tables
    INSERT INTO <archive-table> SELECT * FROM <source-table>;

    To run multiple statements, submit them as multiple separate faz query calls — one statement per call.

  • No connection pooling. Each query opens and closes a connection, which adds ~5-15 ms of overhead per request. Heavy workloads should front faz with ProxySQL.

  • MariaDB-specific syntax (e.g. ROW_FORMAT=COMPRESSED table options) isn't validated by sqlglot's MySQL dialect. The connector executes them; the safety pipeline doesn't have explicit rules for MariaDB-only DDL.

Troubleshooting

Can't connect to MySQL server — MySQL isn't listening on the configured host:port. Test with mysql -h <host> -P <port> -u <user>.

Access denied for user 'X'@'host' — credentials are wrong, or the user lacks privileges from this host. MySQL's user table is <user>@<host>-keyed; check SELECT user, host FROM mysql.user.

SSL connection error — your MySQL requires TLS. Set ssl: true.

Schema discovery is sparse — the user lacks SELECT on information_schema. By default, MySQL grants this to all users on tables they have visibility to, but custom grant setups can break it.

For the broader troubleshooting flow, see Connection failed.

On this page