All pages
Powered by GitBook
1 of 19

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Application Development

Application development with MariaDB Connector/Python

Connector/Python

Complete Connector/Python guide: DB API 2.0 (PEP-249) implementation, MariaDB/MySQL connectivity, C+Python architecture, and Connector/C transport.

MariaDB Connector/Python

MariaDB Connector/Python enables python programs to access MariaDB and MySQL databases, using an API which is compliant with the Python DB API 2.0 (PEP-249).

Version 2.0 is currently a Release Candidate (RC); version 1.1 is the latest stable (GA) release. Because 2.0 is not yet GA, install it with the --pre flag (for example pip install --pre mariadb); a plain pip install mariadb installs the latest stable release (1.1). See the page for details. Do not use non-stable (non-GA) releases in production.

About Connector/Python

Overview of MariaDB Connector/Python: a PEP-249-compliant DB API 2.0 driver supporting sync and async operations, available as pure Python, a C extension, or pre-compiled binary wheels.

Installation

Install MariaDB Connector/Python via pip with pure Python, C extension, or binary wheel options; connection pooling requires the separate mariadb[pool] extra.

Basic usage of MariaDB Connector/Python covers connecting, parameterized queries with execute and executemany, and NULL and default value handling with indicators.

Async/await support in MariaDB Connector/Python 2.0 enables non-blocking database operations via asyncConnect, AsyncCursor, and create_async_pool for asyncio-based Python applications.

MariaDB Connector/Python 2.0 connection pooling supports sync and async pools via create_pool and create_async_pool, with configurable size, health checks, and context managers.

Migration from MariaDB Connector/Python 1.1 to 2.0 covers renamed parameters, removed auto-reconnect, updated pooling, URI connections, async/await support, and a migration checklist.

Application development with MariaDB Connector/Python.

MariaDB Connector/Python API reference covers the module, connection class, cursor class, async/await support, connection pooling, and constants used in Python database applications.

MariaDB Connector/Python is licensed under the GNU LGPL v2.1; the accompanying documentation is covered by the Creative Commons Attribution 3.0 license.

MariaDB Connector/Python bug reports are filed in the Jira CONPY project. Effective reports include version details, a short reproducing script, and table definitions where relevant.

Set up the test database, contacts and accounts tables, and a user account required by the MariaDB Connector/Python code examples in this documentation.

MariaDB Connector/Python transactions default to manual commit; the Connection class provides commit and rollback, with async transaction support via asyncConnect in version 2.0.

MariaDB Connector/Python FAQ addresses common installation issues, migration from 1.1 to 2.0, the binary vs text protocol distinction, async setup, and transaction commit requirements.

About Connector/Python

Overview of MariaDB Connector/Python: a PEP-249-compliant DB API 2.0 driver supporting sync and async operations, available as pure Python, a C extension, or pre-compiled binary wheels.

MariaDB Connector/Python enables python programs to access MariaDB and MySQL databases, using an API which is compliant with the Python DB API 2.0 (PEP-249).

Version 2.0 offers flexible distribution options:

  • Pure Python - Works on all platforms, no compiler required

  • C extension

- Maximum performance (2-12× faster on data-heavy workloads)
  • Pre-compiled wheels - No MariaDB Connector/C installation needed

  • All implementations support both synchronous and asynchronous operations.

    MariaDB Connector/Python connects to MariaDB and MySQL database servers. Individual server-side features may require a minimum server version; those requirements are noted with the feature.

    The following MariaDB Connector/Python release series are currently supported:

    Release Series
    Stable (GA) Date

    1.1

    June 2022

    For End of Standard Support and End of Life dates, see the MariaDB Engineering Policy.

    Version 2.0 (currently 2.0.0rc2) is a Release Candidate and is not yet a supported release series.

    Requirement
    1.1 (GA)
    2.0 (RC)

    Python

    CPython 3.9 through 3.14

    CPython 3.10 or later

    MariaDB Connector/C

    3.3.1 or later, always required

    3.3.1 or later, and only for the c and binary extras — the pure Python build requires none

    Connector/Python reports both its own version and the version of the underlying MariaDB Connector/C:

    Installation — version 1.1 (stable / GA):

    A plain pip3 install installs the latest stable release (1.1). It always installs the C extension and requires MariaDB Connector/C to be pre-installed; connection pooling is included by default.

    Installation — version 2.0 (Release Candidate):

    Version 2.0 is a pre-release, so the --pre flag is required — without it, pip installs the latest GA release (1.1).

    • Documentation

    • Bug tracker

    • Sources are hosted on Github

    This page is covered by the Creative Commons Attribution 3.0 license.

    The most recent release of MariaDB Connector/Python is:

    Download Connector/Python 1.1.14

    import mariadb
    
    print(mariadb.__version__)          # connector version, e.g. '1.1.14'
    print(mariadb.__version_info__)     # same, as a tuple: (1, 1, 14)
    print(mariadb.client_version)       # MariaDB Connector/C version, numeric
    print(mariadb.client_version_info)  # MariaDB Connector/C version, as a tuple
    # Latest stable release (1.1)
    $ pip3 install mariadb
    
    # Pin to a specific 1.1 release
    $ pip3 install mariadb==1.1.14
    # Pure Python (default)
    $ pip3 install --pre mariadb
    
    # C extension for maximum performance
    $ pip3 install --pre mariadb[c]
    
    # Pre-compiled binary wheels
    $ pip3 install --pre mariadb[binary]
    
    # With connection pooling
    $ pip3 install --pre mariadb[binary,pool]

    Version 1.1 is the latest stable (GA) release; version 2.0 is currently a Release Candidate (RC). Choose the version that fits your needs below. Do not use non-stable (non-GA) releases in production.

    Supported Versions

    Server Compatibility

    Supported Release Series

    Requirements

    Checking Your Installed Version

    Installation

    Links

    Basic Usage
    Async/Await Support
    Connection Pooling
    Migration Guide: 1.1 to 2.0
    Application Development
    API Reference
    License
    Bug Reports
    Setup for Examples
    Transactions with MariaDB Connector/Python
    MariaDB Connector/Python FAQ
    Installation

    Installation

    Install MariaDB Connector/Python via pip with pure Python, C extension, or binary wheel options; connection pooling requires the separate mariadb[pool] extra.

    • - Connection parameters, methods, and attributes

    • - Cursor parameters, methods, and attributes

    • - Pool configuration and usage

    API Reference

    MariaDB Connector/Python API reference covers the module, connection class, cursor class, async/await support, connection pooling, and constants used in Python database applications.

    The MariaDB Connector/Python module provides connect, asyncConnect, create_pool, and create_async_pool constructors, DB API 2.0 type objects, and the exception hierarchy.

    The ConnectionPool class

    MariaDB Connector/Python ConnectionPool manages a fixed-size pool with methods to add, retrieve, and close connections, plus attributes reporting pool size and connection state.

    Class defining a pool of database connections

    MariaDB Connector/Python supports simple connection pooling. A connection pool holds a number of open connections and handles thread safety when providing connections to threads.

    The size of a connection pool is configurable at creation time, but cannot be changed afterward. The maximum size of a connection pool is limited to 64 connections.

    Keyword Arguments:

    • `pool_name` (str

    Bug Reports

    MariaDB Connector/Python bug reports are filed in the Jira CONPY project. Effective reports include version details, a short reproducing script, and table definitions where relevant.

    If you think that you have found a bug in MariaDB Software, please report it at and file it under Project CONPY (abbreviation for Connector/Python).

    Always search the bug database first. Especially if you are using an older version of MariaDB Connector/Python it could be reported already by someone else or it was already fixed in a more recent version.

    We need to know what you did, what happened and what you wanted to happen. A report stating that method xyz() hangs, will not allow us to provide you with an advice or fix, since we just don’t know what the method is doing. Beside versions, a good bug report contains a short script which reproduces the problem. Sometimes it is also necessary to provide the definition (and data) of used tables.

    MariaDB Connector/Python interacts with two other components: The database server and MariaDB Connector/C. The latter one is responsible for client/server communication. An error does not necessarily have to exist in Connector / Python; it can also be an error in the database server or in Connector/C. In this case, we will reclassify the bug (MDEV or CONC).

    MariaDB Connector/Python 2.0 supports
    • Python 3.10 and later

    • MariaDB server versions from version 10.3 or MySQL server versions from version 5.7.

    • MariaDB client library (MariaDB Connector/C) from version 3.3.1 (optional - only required for C extension).

    Version 1.1 is the current GA release. A plain pip install installs the latest stable version:

    To pin to a specific 1.1 release:

    Version 1.1:

    • Always installs the C extension

    • Requires MariaDB Connector/C to be pre-installed

    • Does not support pure Python or binary wheels

    • Connection pooling is included by default

    For version 1.1 documentation, see the 1.1 branch documentation.

    MariaDB Connector/Python 2.0 offers three installation options:

    Works everywhere, no compiler or C dependencies required:

    This is the default installation method for 2.0. The pure Python implementation:

    • Works on all Python interpreters (CPython, PyPy, etc.)

    • Requires no compilation or system dependencies

    • Provides good performance for most use cases

    • Fully compatible with the C extension API

    For maximum performance, install the C extension:

    The C extension:

    • Delivers 2-12× better performance on data-heavy workloads

    • Requires MariaDB Connector/C to be pre-installed on your system

    • Requires a C compiler for building from source

    • Provides the same API as the pure Python implementation

    Pre-compiled wheels with no local C connector required:

    Binary wheels:

    • Include the C extension pre-compiled

    • MariaDB Connector/C is bundled - no separate installation needed

    • No compiler required

    • Available for common platforms (Windows, Linux, macOS)

    Connection pooling is now a separate optional package:

    Or combine with binary wheels:

    Option 1: Binary wheels (recommended)

    Option 2: Pure Python

    Option 3: C extension from source

    First install MariaDB Connector/C. MSI installers for both 32-bit and 64-bit operating systems are available from MariaDB Connector Download page.

    Then install the C extension:

    On success, you should see a message at the end "Successfully installed mariadb-2.0.0rc2".

    The pure Python implementation has minimal requirements:

    No compiler or system dependencies required.

    To build the C extension from source, you will need:

    • C compiler (gcc, clang, or MSVC)

    • Python development files (Usually installed with package python3-dev). Minimum supported version is Python 3.10 (version 1.1 requires Python 3.8).

    • MariaDB Connector/C libraries and header files (version 3.3.1 or later)

      • Either from MariaDB server package or from MariaDB Connector/C package

      • If your distribution doesn't provide a recent version, download from or build from source

    • The mariadb_config program from MariaDB Connector/C (must be in your PATH)

    • For POSIX systems: TLS libraries (GnuTLS or OpenSSL)

    • Python's "packaging" module

    On POSIX systems, ensure the PATH environment variable contains the directory with the mariadb_config utility.

    Installing the C extension from source:

    Installing with pooling support:

    For troubleshooting, check the Installation FAQ.

    If you have installed the sources, after successful build you can run the test suite from the source directory.

    You can configure the connection parameters by using the following environment variables

    • TEST_DB_USER (default root)

    • TEST_DB_PASSWORD

    • TEST_DB_DATABASE (default ‘testp’)

    • TEST_DB_HOST (default ‘localhost’)

    • TEST_DB_PORT (default 3306)

    API Reference

    Prerequisites

    Connection API
    Cursor API
    Connection Pooling API
    pip install mariadb
    pip install mariadb==1.1.14
    pip install --pre mariadb
    pip install --pre mariadb[c]
    pip install --pre mariadb[binary]
    pip install --pre mariadb[pool]
    pip install --pre mariadb[binary,pool]
    pip install --pre mariadb[binary,pool]
    pip install --pre mariadb[pool]
    pip install --pre mariadb[c,pool]
    Collecting mariadb
    Downloading mariadb-2.0.0rc2-cp311-cp311-win_amd64.whl (210 kB)
    ---------------------------------------- 210.0/210.0 kB 3.2 MB/s eta 0:00:00
    Installing collected packages: mariadb
    Successfully installed mariadb-2.0.0rc2
    cd source_package_dir
    pip install .
    cd source_package_dir
    pip install mariadb-c/
    cd source_package_dir
    pip install mariadb-pool/
    pytest tests/ -v

    Installation Options

    Version 2.0 is currently a Release Candidate (RC); version 1.1 is the latest stable (GA) release.

    Because 2.0 is not yet GA, a plain pip install mariadb installs the latest stable release (1.1). To install the 2.0 release candidate you must pass the --pre flag, for example pip install --pre mariadb. Do not use non-stable (non-GA) releases in production.

    Installing Version 1.1 (Stable / GA)

    Installing Version 2.0 (Release Candidate)

    Version 2.0 is a Release Candidate. The --pre flag is required so that pip will select the pre-release; without it, pip installs the latest GA release (1.1).

    1. Pure Python (Default)

    2. C Extension (Maximum Performance)

    3. Pre-compiled Binary Wheels

    4. With Connection Pooling

    Microsoft Windows

    Installation from Source

    Pure Python Installation

    C Extension Build Prerequisites

    Test suite

    The connection class

    MariaDB Connector/Python Connection class reference covers parameters, methods for commit and rollback, and read-only attributes for server version and TLS state.

    The cursor class

    MariaDB Connector/Python Cursor class documents parameters, execute and fetch methods, and attributes such as rowcount, description, and sp_outparams for stored procedures.

    The ConnectionPool class

    MariaDB Connector/Python ConnectionPool manages a fixed-size pool with methods to add, retrieve, and close connections, plus attributes reporting pool size and connection state.

    Constants

    MariaDB Connector/Python constants module defines groups: CAPABILITY, CLIENT, CURSOR, FIELD_TYPE, FIELD_FLAG, INDICATOR, STATUS, and EXT_FIELD_TYPE.

    The MariaDB Connector/Python module
    ) - Name of connection pool
  • `pool_size` (int) - Size of pool. The Maximum allowed number is 64. Default to 5

  • `pool_reset_connection` (bool) - Will reset the connection before returning it to the pool. Default to True.

  • `pool_validation_interval` (int) - Specifies the validation interval in milliseconds after which the status of a connection requested from the pool is checked. A value of 0 means that the status will always be checked. Default to 500 (Added in version 1.1.6)

  • **kwargs - Optional additional connection arguments, as described in mariadb.connect() method.

  • Adds a connection object to the connection pool.

    In case that the pool doesn’t have a free slot or is not configured, a PoolError exception will be raised.

    Closes connection pool and all connections.

    Returns a connection from the connection pool or raises a PoolError exception if a connection is not available.

    Sets the connection configuration for the connection pool. For valid connection arguments, check the mariadb.connect() method.

    Note: This method doesn’t create connections in the pool. To fill the pool, one has to use add_connection() ḿethod.

    Returns the number of connections in connection pool.

    Since version 1.1.0

    Returns the maximum size for connection pools.

    Returns the size of the connection pool.

    Returns the name of the connection pool.

    class ConnectionPool(*args, **kwargs)

    ConnectionPool methods

    ConnectionPool.add_connection(connection=None)

    ConnectionPool.close()

    ConnectionPool.get_connection()

    ConnectionPool.set_config(**kwargs)

    ConnectionPool attributes

    ConnectionPool.connection_count

    ConnectionPool.max_size

    ConnectionPool.pool_size

    ConnectionPool.pool_name

    Use copy and paste instead. Screenshots create a lot more data volume and are often difficult to read on mobile devices. Typing program code from a screenshot is also an unnecessary effort.

    Scripts which are longer than 10 lines often contain code which is not relevant to the problem and increases the time to figure out the real problem. So try to keep it simple and focus on the real problem.

    The sane applies for database related components like tables, views, and stored procedures. Avoid table definitions with hundreds of columns if the problem can be reproduced with only 4 columns.

    If you have encountered two or more bugs which are not related, please file an issue for each of them.

    If your application crashes, please also provide if possible a backtrace and output of the exception.

    How to report a bug?

    Search first

    What?

    Versions of components

    Avoid screenshots!

    Jira issue tracker

    Keep it simple!

    Only report one problem in one bug report

    Crashes

    Report bugs in English only!

    License

    MariaDB Connector/Python is licensed under the GNU LGPL v2.1; the accompanying documentation is covered by the Creative Commons Attribution 3.0 license.

    MariaDB Connector/Python

    MariaDB Connector/Python is licensed under the GNU Lesser General Public License v2.1

    MariaDB Connector/Python documentation

    The documentation for MariaDB Connector/Python is covered by the Creative Commons Attribution 3.0 license.

    You are free, to : - Share, copy and redistribute the material in any medium or format

    • Adapt, remix, transform, and build upon the material for any purpose, even commercially.

    under the following terms : - Attribution – You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.

    • No additional restrictions —- You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.

    Setup for Examples

    Set up the test database, contacts and accounts tables, and a user account required by the MariaDB Connector/Python code examples in this documentation.

    The examples in this MariaDB Connector/Python documentation depend on a database test and tables contacts and accounts.

    Create the Schema

    1. Create a test database if one does not exist with the statement:

      CREATE DATABASE IF NOT EXISTS test;
    2. Create tables in the test database for testing basic and advanced operations with statements:

    1. Create a user account to test connectivity with the statement:

    2. Ensure that the user account has privileges to access the tables with the statement:

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    spinner
    MariaDB Connector Download page
    spinner
    spinner
    spinner
    spinner
    spinner
    CREATE TABLE test.contacts (
       id INT PRIMARY KEY AUTO_INCREMENT,
       first_name VARCHAR(25),
       last_name VARCHAR(25),
       email VARCHAR(100)
    ) ENGINE=InnoDB;
    
    CREATE TABLE test.accounts (
       id INT PRIMARY KEY AUTO_INCREMENT,
       first_name VARCHAR(25),
       last_name VARCHAR(25),
       email VARCHAR(100),
       amount DECIMAL(15,2) CHECK (amount >= 0.0),
       UNIQUE (email)
    ) ENGINE=InnoDB;
    CREATE USER 'db_user'@'192.0.2.1'
       IDENTIFIED BY 'db_user_password';
    GRANT SELECT, INSERT, UPDATE, DELETE, DROP
       ON test.contacts
       TO 'db_user'@'192.0.2.1';
    
    GRANT SELECT, INSERT, UPDATE, DELETE, DROP
       ON test.accounts
       TO 'db_user'@'192.0.2.1';

    Create the User

    spinner
    spinner

    Connection Pooling

    MariaDB Connector/Python 2.0 connection pooling supports sync and async pools via create_pool and create_async_pool, with configurable size, health checks, and context managers.

    Since version 2.0: Connection pooling is now a separate optional package. Install with:

    pip install --pre mariadb[pool]

    Version 2.0 is currently a Release Candidate (RC), so the --pre flag is required. Version 1.1 (the latest stable/GA release) includes connection pooling by default.

    A connection pool is a cache of connections to a database server where connections can be reused for future requests. Since establishing a connection is resource-expensive and time-consuming, especially when used inside a middle tier environment which maintains multiple connections and requires connections to be immediately available on the fly.

    Especially for server-side web applications, a connection pool is the standard way to maintain a pool of database connections which are reused across requests.

    Version 2.0 introduces:

    • Synchronous pools with create_pool()

    • Asynchronous pools with create_async_pool()

    • Improved API with min_size and max_size parameters

    • Context manager support with acquire()

    The typical way for creating and using a connection pool is:

    1. Create (and configure) a connection pool

    2. Obtain a connection from connection pool using acquire()

    3. Perform database operation(s)

    Since version 2.0

    Create a synchronous connection pool using create_pool():

    Pool Configuration Parameters:

    • min_size (int) - Minimum number of connections in the pool. Default: same than max_size

    • max_size (int) - Maximum number of connections in the pool. Default: 10

    Connection Release Behavior:

    When a connection is returned to the pool (either explicitly or via context manager), the pool automatically handles cleanup:

    1. If reset_connection=True: Calls conn.reset() to clear all session state (session variables, temporary tables, prepared statements) without reconnecting. This ensures a clean state for the next user but adds overhead.

    2. If reset_connection=False (default): Checks if the connection has an active transaction. If a transaction is in progress, it automatically calls conn.rollback() to prevent transaction leakage between pool users.

    Best Practices:

    • Use reset_connection=True if you need guaranteed clean state (e.g., different users sharing a pool with session-specific settings)

    • Use reset_connection=False (default) for better performance when session state doesn't matter

    • Always commit or rollback transactions explicitly before releasing connections for clarity

    Connection Parameters:

    • All connection parameters from mariadb.connect() are supported (host, user, password, database, ssl_ca, etc.)

    Example - Synchronous Pool:

    Example - Connection Parameters:

    The pool factories do not accept a connection URI string; pass connection settings as keyword arguments.

    Since version 2.0

    Create an asynchronous connection pool for async/await applications:

    Version 1.1:

    Version 2.0:

    Return the connection to the pool (automatically with context managers)
    max_idle_time (float) - Maximum time (seconds) a connection can be idle before being closed. Default: 600.0 (10 minutes)
  • max_lifetime (float) - Maximum lifetime (seconds) of a connection before being replaced. Default: 3600.0 (1 hour)

  • validation_interval (float) - Interval (seconds) between health checks. Default: 30.0

  • acquire_timeout (float) - Timeout (seconds) when acquiring a connection from the pool. Default: 30.0

  • enable_health_check (bool) - Enable periodic health checks on pooled connections. Default: True

  • reset_connection (bool) - Reset connection state when returning to pool (clears session variables, temporary tables, and prepared statements). Default: False

  • ping_threshold (float) - Ping connection if idle for more than this many seconds (0 = disabled). Default: 0.25

  • Configuring and using a connection pool

    Synchronous Connection Pool

    Asynchronous Connection Pool

    FastAPI Example

    Migration from Version 1.1

    spinner
    import mariadb
    
    # Create pool with configuration
    pool = mariadb.create_pool(
        host="localhost",
        user="example_user",
        password="GHbe_Su3B8",
        database="test",
        min_size=5,
        max_size=20,
        max_idle_time=600.0,
        max_lifetime=3600.0,
        ping_threshold=0.25,
        enable_health_check=True
    )
    
    # Acquire connection from pool
    with pool.acquire() as conn:
        with conn.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM users")
            count = cursor.fetchone()[0]
            print(f"Total users: {count}")
    
    # Connection automatically returned to pool
    pool = mariadb.create_pool(
        host="localhost",
        user="example_user",
        password="GHbe_Su3B8",
        database="test",
        min_size=10,
        max_size=50
    )
    import asyncio
    import mariadb
    
    async def main():
        # Create async pool with configuration
        pool = await mariadb.create_async_pool(
            host="localhost",
            user="example_user",
            password="GHbe_Su3B8",
            database="test",
            min_size=5,
            max_size=20,
            max_idle_time=600.0,
            acquire_timeout=30.0,
            enable_health_check=True
        )
        
        # Acquire connection from pool
        async with await pool.acquire() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("SELECT COUNT(*) FROM users")
                count = (await cursor.fetchone())[0]
                print(f"Total users: {count}")
        
        # Close pool when done
        await pool.close()
    
    asyncio.run(main())
    from fastapi import FastAPI
    from contextlib import asynccontextmanager
    import mariadb
    
    pool = None
    
    @asynccontextmanager
    async def lifespan(app: FastAPI):
        global pool
        # Startup: Create pool
        pool = await mariadb.create_async_pool(
            host="localhost",
            user="user",
            password="password",
            database="mydb",
            min_size=10,
            max_size=50
        )
        yield
        # Shutdown: Close pool
        await pool.close()
    
    app = FastAPI(lifespan=lifespan)
    
    @app.get("/users/{user_id}")
    async def get_user(user_id: int):
        async with await pool.acquire() as conn:
            async with conn.cursor(dictionary=True) as cursor:
                await cursor.execute(
                    "SELECT id, name, email FROM users WHERE id = ?",
                    (user_id,)
                )
                return await cursor.fetchone()
    pool = mariadb.ConnectionPool(
        pool_name="mypool",
        pool_size=10,
        host="localhost",
        user="user",
        password="password"
    )
    conn = pool.get_connection()
    # Install pooling package first (--pre is required while 2.0 is an RC)
    # pip install --pre mariadb[pool]
    
    pool = mariadb.create_pool(
        host="localhost",
        user="user",
        password="password",
        min_size=5,
        max_size=10
    )
    
    with pool.acquire() as conn:
        # Use connection
        pass

    Basic Usage

    Basic usage of MariaDB Connector/Python covers connecting, parameterized queries with execute and executemany, and NULL and default value handling with indicators.

    API Reference

    • Connection API - Connection parameters, methods, and attributes

    • Cursor API - Cursor parameters, methods, and attributes

    • Connection Pooling API - Pool configuration and usage

    Connecting

    The basic usage of MariaDB Connector/Python is similar to other database drivers which implement DB API 2.0 ().

    Since version 2.0: Connections can be established using URI strings or keyword arguments.

    Below is a simple example of a typical use of MariaDB Connector/Python

    Alternative - Keyword Arguments:

    Output:

    Before MariaDB Connector/Python can be used, the MariaDB Connector/Python module must be imported. Once the mariadb module is loaded, a connection to a database server will be established using the method .

    In order to be able to communicate with the database server in the form of SQL statements, a cursor object must be created first.

    The method name cursor may be a little misleading: unlike a cursor in MariaDB that can only read and return data, a cursor in Python can be used for all types of SQL statements.

    After creating the table mytest, everything is ready to insert some data: Column values that are to be inserted in the database are identified by place holders, the data is then passed in the form of a tuple as a second parameter.

    After creating and populating the table mytest the cursor will be used to retrieve the data.

    At the end we free resources and close cursor and connection.

    As shown in previous example, passing parameters to SQL statements happens by using placeholders in the statement. By default MariaDB Connector/Python uses a question mark as a placeholder, for compatibility reason also %s placeholders are supported. Passing parameters is supported in methods execute() and executemany() of the cursor class.

    By default, the text protocol is used for parameter binding. For binary protocol (prepared statements), set binary=True at the cursor level; since version 2.0 binary=True can also be set at the connection level (in connect() or via a URI). Parameter escaping is handled automatically by the connector.

    Using Binary Protocol (Prepared Statements):

    Often there is a requirement to update, delete or insert multiple records. This could be done be using execute() in a loop, but much more effective is using the executemany() method. The executemany() works similar to execute(), but accepts data as a list of tuples:

    When using executemany(), there are a few restrictions:

    • All tuples must have the same types as in first tuple. E.g. the parameter [(1),(1.0)] or [(1),(None)] are invalid.

    • Special values like None or column default value needs to be indicated by an indicator.

    In certain situations, for example when inserting default values or NULL, special indicators must be used.

    Beside the default indicator which inserts the default value of 1.99, the following indicators are supported: : * INDICATOR.IGNORE: Ignores the value (only update commands)

    • INDICATOR.NULL: Value is NULL

    • INDICATOR.IGNORE_ROW: Don’t update or insert row

    • Mixing different parameter styles is not supported and will raise an exception

    • The Python string operator % must not be used. The execute() method accepts a tuple or list as second parameter.

    • Placeholders between quotation marks are interpreted as a string.

    Several standard python types are converted into SQL types and returned as Python objects when a statement is executed.

    Python type
    SQL type

    Parameters for execute() needs to be passed as a tuple. If only one parameter will be passed, tuple needs to contain a comma at the end.

  • Parameters for executemany() need to be passed as a list of tuples.

  • Decimal

    DECIMAL

    Long

    TINYINT, SMALLINT, INT, BIGINT

    String

    VARCHAR, VARSTRING, TEXT

    ByteArray, Bytes

    TINYBLOB, MEDIUMBLOB, BLOB, LONGBLOB

    DateTime

    DATETIME

    Date

    DATE

    Time

    TIME

    Timestamp

    TIMESTAMP

    None

    NULL

    Bool

    TINYINT

    Float, Double

    DOUBLE

    Passing parameters to SQL statements

    Using indicators

    NOTE

    Supported Data types

    Supported Data Types

    PEP-249
    connect()
    spinner
    import mariadb
    
    # Establish a connection using URI
    with mariadb.connect("mariadb://example_user:GHbe_Su3B8@localhost/test") as conn:
        with conn.cursor() as cursor:
            # Populate countries table with some data
            cursor.execute("INSERT INTO countries(name, country_code, capital) VALUES (?,?,?)",
                ("Germany", "GER", "Berlin"))
    
            # retrieve data
            cursor.execute("SELECT name, country_code, capital FROM countries")
    
            # print content
            row = cursor.fetchone()
            print(*row, sep=' ')
    import mariadb
    
    # connection parameters
    conn_params = {
        "user": "example_user",
        "password": "GHbe_Su3B8",
        "host": "localhost",
        "database": "test"
    }
    
    # Establish a connection
    with mariadb.connect(**conn_params) as conn:
        with conn.cursor() as cursor:
            cursor.execute("INSERT INTO countries(name, country_code, capital) VALUES (?,?,?)",
                ("Germany", "GER", "Berlin"))
            cursor.execute("SELECT name, country_code, capital FROM countries")
            row = cursor.fetchone()
            print(*row, sep=' ')
    Germany GER Berlin
    import mariadb
    
    # Establish a connection using URI
    with mariadb.connect("mariadb://example_user:GHbe_Su3B8@localhost/test") as conn:
        with conn.cursor() as cursor:
            sql = "INSERT INTO countries (name, country_code, capital) VALUES (?,?,?)"
            data = ("Germany", "GER", "Berlin")
            cursor.execute(sql, data)
    
            conn.commit()
    
            # delete last entry
            sql = "DELETE FROM countries WHERE country_code=?"
            data = ("GER",)
            cursor.execute(sql, data)
    
            conn.commit()
    import mariadb
    
    # Enable binary protocol at connection level
    with mariadb.connect("mariadb://example_user:GHbe_Su3B8@localhost/test?binary=true") as conn:
        with conn.cursor() as cursor:
            # All queries use binary protocol (prepared statements)
            sql = "INSERT INTO countries (name, country_code, capital) VALUES (?,?,?)"
            data = ("Germany", "GER", "Berlin")
            cursor.execute(sql, data)
            conn.commit()
    import mariadb
    
    # Establish a connection using URI
    with mariadb.connect("mariadb://example_user:GHbe_Su3B8@localhost/test") as connection:
        with connection.cursor() as cursor:
            sql = "INSERT INTO countries (name, country_code, capital) VALUES (?,?,?)"
    
            data = [("Ireland", "IE", "Dublin"),
                   ("Italy", "IT", "Rome"),
                   ("Malaysia", "MY", "Kuala Lumpur"),
                   ("France", "FR", "Paris"),
                   ("Iceland", "IS", "Reykjavik"),
                   ("Nepal", "NP", "Kathmandu")]
    
            # insert data
            cursor.executemany(sql, data)
    
            # Since autocommit is off by default, we need to commit last transaction
            connection.commit()
    
            # Instead of 3 letter country-code, we inserted 2 letter country code, so
            # let's fix this mistake by updating data
            sql = "UPDATE countries SET country_code=? WHERE name=?"
            data = [("IRL", "Ireland"),
                   ("ITA", "Italy"),
                   ("MYS", "Malaysia"),
                   ("FRA", "France"),
                   ("ISL", "Iceland"),
                   ("NPL", "Nepal")]
            cursor.executemany(sql, data)
    
            # Now let's delete all non European countries
            sql = "DELETE FROM countries WHERE name=?"
            data = [("Malaysia",), ("Nepal",)]
            cursor.executemany(sql, data)
    
            # by default autocommit is off, so we need to commit
            # our transactions
            connection.commit()
    import mariadb
    from mariadb.constants import INDICATOR
    
    # Establish a connection using URI
    with mariadb.connect("mariadb://example_user:GHbe_Su3B8@localhost/test") as connection:
        with connection.cursor() as cursor:
            cursor.execute("DROP TABLE IF EXISTS cakes")
            cursor.execute("CREATE TABLE cakes(id int, cake varchar(100), price decimal(10,2) default 1.99)")
    
            sql = "INSERT INTO cakes (id, cake, price) VALUES (?,?,?)"
            data = [(1, "Cherry Cake", 2.10), (2, "Apple Cake", INDICATOR.DEFAULT)]
            cursor.executemany(sql, data)
            connection.commit()

    Transactions with MariaDB Connector/Python

    MariaDB Connector/Python transactions default to manual commit; the Connection class provides commit and rollback, with async transaction support via asyncConnect in version 2.0.

    API Reference

    • Connection API - Connection parameters, methods, and attributes

    • Cursor API - Cursor parameters, methods, and attributes

    • Connection Pooling API - Pool configuration and usage

    A database transaction is a single unit of logic. A transaction can consist of one or more database operations. Transactions are useful and sometimes essential in several types of data operations. For example, many applications require that a set of SQL statements either complete, or fail, as a single unit.

    The common characteristics of transactions are atomicity, consistency, isolation, and durability, what is termed as ACID (atomic, consistent, isolated, durable) transactions. MariaDB transactions are .

    You can enable auto-committed transactions using the autocommit connection attribute.

    By default, MariaDB Connector/Python disables auto-commit. With auto-commit disabled transactions must be committed explicitly.

    You may want to use explicit transactions so that either all statements are committed together or all statements are completely rolled back. For example, explicit transactions are almost always necessary for financial transactions. Otherwise, a situation could occur where, money is removed from the payer's account, but it is not properly moved to the payee's account.

    To use explicit transactions, MariaDB's standard transaction related statements can be executed with MariaDB Connector/Python using a cursor:

    Additionally, instances of the Connection class can use the commit() and rollback() methods instead.

    The following example shows how to update the example table accounts created in . The email data is updated from the format firstnamelastname@example.com to the new format firstname.lastname@example.com. Call the functions to update data in a transaction. Because the updates are made within a transaction, either all contacts' emails are updated to the new format, or none are.

    • The functions to add and update account data must be defined before being called with regards to their ordering in the script.

    • The add_account() function adds a new account to the table.

    • The execute() method is called on the cursor in the add_account()

    Confirm the test.accounts table was properly updated by using to execute a statement:

    MariaDB Connector/Python disables auto-committing transactions by default, following the PEP-249 DBAPI 2.0 specification.

    To auto-commit transactions, enable auto-commit either when initializing a connection or by manually setting the autocommit connection attribute.

    To enable auto-commit using connect():

    To enable auto-commit using autocommit connection attribute:

    With auto-commit enabled, MariaDB Connector/Python commits a transaction after each statement executes.

    Version 2.0 introduces native async/await support for transactions:

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Constants

    MariaDB Connector/Python constants module defines groups: CAPABILITY, CLIENT, CURSOR, FIELD_TYPE, FIELD_FLAG, INDICATOR, STATUS, and EXT_FIELD_TYPE.

    Constants are declared in mariadb.constants module.

    For using constants of various types, they have to be imported first:

    MariaDB capability flags.

    These flags are used to check the capabilities both of a MariaDB server or the client application.

    Capability flags are defined in module mariadb.constants.CAPABILIY

    Since version 1.1.4

    The MariaDB Connector/Python module

    The MariaDB Connector/Python module provides connect, asyncConnect, create_pool, and create_async_pool constructors, DB API 2.0 type objects, and the exception hierarchy.

    MariaDB Connector/Python module enables python programs to access MariaDB and MySQL databases, using an API which is compliant with the Python DB API 2.0 (PEP-249).

    Creates a MariaDB Connection object.

    The first positional argument, when given, is a connection URI string (see Since version 2.0 below). By default, the standard Connection class is used.

    Parameter connectionclass specifies a subclass of the standard Connection class. If not specified, the default is used. This optional parameter was added in version 1.1.0.

    Since version 2.0: Connection can be established using a URI string or keyword arguments. Keyword arguments override URI values when both are provided.

    Output:

    MariaDB capability flags.

    These flags are used to check the capabilities both of a MariaDB server or the client application.

    Capability flags are defined in module mariadb.constants.CLIENT

    Since version 1.1.0, deprecated in 1.1.4

    Cursor constants are used for server side cursors. Currently only read only cursor is supported.

    Cursor constants are defined in module mariadb.constants.CURSOR.

    Since version 1.1.0

    This is the default setting (no cursor)

    Will create a server side read only cursor. The cursor is a forward cursor, which means it is not possible to scroll back.

    Using ERR constants instead of error numbers make the code more readable. Error constants are defined in constants.ERR module

    Since version 1.1.2

    Output:

    MariaDB FIELD_FLAG Constants

    These constants represent the various field flags. As an addition to the DBAPI 2.0 standard (PEP-249) these flags are returned as eighth element of the cursor description attribute.

    Field flags are defined in module mariadb.constants.FIELD_FLAG

    Since version 1.1.0

    column is defined as not NULL

    column is (part of) a primary key

    column is (part of) a unique key

    column is (part of) a key

    column contains a binary object

    numeric column is defined as unsigned

    column has zerofill attribute

    column is a binary

    column is defined as enum

    column is an auto_increment column

    column is defined as time stamp

    column is defined as SET

    column hasn’t a default value

    column will be set to current timestamp on UPDATE

    column contains numeric value

    column is part of a key

    MariaDB FIELD_TYPE Constants

    These constants represent the field types supported by MariaDB. The field type is returned as second element of cursor description attribute.

    Field types are defined in module mariadb.constants.FIELD_TYPE

    column type is TINYINT (1-byte integer)

    column type is SMALLINT (2-byte integer)

    column type is INT (4-byte integer)

    column type is FLOAT (4-byte single precision)

    column type is DOUBLE (8-byte double precision)

    column type is NULL

    column type is TIMESTAMP

    column type is BIGINT (8-byte Integer)

    column type is MEDIUMINT (3-byte Integer)

    column type is DATE

    column type is TIME

    column type is DATETIME

    column type is YEAR

    column type is VARCHAR

    column type is BIT

    column type is JSON

    column type is DECIMAL

    column type is ENUM

    column type is SET

    column type is TINYBLOB (max. length of 255 bytes)

    column type is MEDIUMBLOB (max. length of 16,777,215 bytes)

    column type is LONGBLOB (max. length 4GB bytes)

    column type is BLOB (max. length of 65.535 bytes)

    column type is VARCHAR (variable length)

    column type is CHAR (fixed length)

    column type is GEOMETRY

    Indicator values are used in executemany() method of cursor class to indicate special values when connected to a MariaDB server 10.2 or newer.

    indicates a NULL value

    indicates to use default value of column

    indicates to ignore value for column for UPDATE statements. If set, the column will not be updated.

    indicates not to update the entire row.

    For internal use only

    For internal use only

    The STATUS constants are used to check the server status of the current connection.

    Since version 1.1.0

    Example:

    if (connection.server_status & STATUS.SP_OUT_PARAMS): print("retrieving output parameters from store procedure") ... else: print("retrieving data from stored procedure") ....

    Pending transaction

    Server operates in autocommit mode

    The result from last executed statement contained two or more result sets which can be retrieved by cursors nextset() method.

    The last executed statement didn’t use a good index.

    The last executed statement didn’t use an index.

    The last executed statement opened a server side cursor.

    For server side cursors this flag indicates end of a result set.

    The current database in use was dropped and there is no default database for the connection anymore.

    Indicates that SQL mode NO_BACKSLASH_ESCAPE is active, which means that the backslash character ‘' becomes an ordinary character.

    The previously executed statement was slow (and needs to be optimized).

    The current result set contains output parameters of a stored procedure.

    The session status has been changed.

    SQL mode ANSI_QUOTES is active.

    Metadata has changed (e.g., table structure modified).

    Pending read-only transaction.

    MariaDB Extended FIELD_TYPE Constants

    These constants represent the extended field types supported by MariaDB. Extended field types provide additional type information beyond standard SQL types.

    Extended field types are defined in module mariadb.constants.EXT_FIELD_TYPE

    No extended type information (value: 0)

    JSON data type (value: 1)

    UUID data type (value: 2)

    IPv4 address data type (value: 3)

    IPv6 address data type (value: 4)

    Geometry POINT type (value: 5)

    Geometry MULTIPOINT type (value: 6)

    Geometry LINESTRING type (value: 7)

    Geometry MULTILINESTRING type (value: 8)

    Geometry POLYGON type (value: 9)

    Geometry MULTIPOLYGON type (value: 10)

    Geometry GEOMETRYCOLLECTION type (value: 11)

    Example:

    Session tracking constants for monitoring session state changes.

    Session tracking constants are defined in module mariadb.constants.SESSION_TRACK

    Since version 2.0

    CAPABILITY

    CLIENT

    CURSOR

    CURSOR.NONE

    CURSOR.READ_ONLY

    ERR (Error)

    FIELD_FLAG

    FIELD_FLAG.NOT_NULL

    FIELD_FLAG.PRIMARY_KEY

    FIELD_FLAG.UNIQUE_KEY

    FIELD_FLAG.MULTIPLE_KEY

    FIELD_FLAG.BLOB

    FIELD_FLAG.UNSIGNED

    FIELD_FLAG.ZEROFILL

    FIELD_FLAG.BINARY

    FIELD_FLAG.ENUM

    FIELD_FLAG.AUTO_INCREMENT

    FIELD_FLAG.TIMESTAMP

    FIELD_FLAG.SET

    FIELD_FLAG.NO_DEFAULT

    FIELD_FLAG.ON_UPDATE_NOW

    FIELD_FLAG.NUMERIC

    FIELD_FLAG.PART_OF_KEY

    FIELD_TYPE

    FIELD_TYPE.TINY

    FIELD_TYPE.SHORT

    FIELD_TYPE.LONG

    FIELD_TYPE.FLOAT

    FIELD_TYPE.DOUBLE

    FIELD_TYPE.NULL

    FIELD_TYPE.TIMESTAMP

    FIELD_TYPE.LONGLONG

    FIELD_TYPE.INT24

    FIELD_TYPE.DATE

    FIELD_TYPE.TIME

    FIELD_TYPE.DATETIME

    FIELD_TYPE.YEAR

    FIELD_TYPE.VARCHAR

    FIELD_TYPE.BIT

    FIELD_TYPE.JSON

    FIELD_TYPE.NEWDECIMAL

    FIELD_TYPE.ENUM

    FIELD_TYPE.SET

    FIELD_TYPE.TINY_BLOB

    FIELD_TYPE.MEDIUM_BLOB

    FIELD_TYPE.LONG_BLOB

    FIELD_TYPE.BLOB

    FIELD_TYPE.VAR_STRING

    FIELD_TYPE.STRING

    FIELD_TYPE.GEOMETRY

    INDICATORS

    INDICATOR.NULL

    INDICATOR.DEFAULT

    INDICATOR.IGNORE

    INDICATOR.IGNORE_ROW

    INFO

    TPC_STATE

    STATUS

    STATUS.IN_TRANS

    STATUS.AUTOCOMMIT

    STATUS.MORE_RESULTS_EXIST

    STATUS.QUERY_NO_GOOD_INDEX_USED

    STATUS.QUERY_NO_INDEX_USED

    STATUS.CURSOR_EXISTS

    STATUS.LAST_ROW_SENT

    STATUS.DB_DROPPED

    STATUS.NO_BACKSLASH_ESCAPES

    STATUS.QUERY_WAS_SLOW

    STATUS.PS_OUT_PARAMS

    STATUS.SESSION_STATE_CHANGED

    STATUS.ANSI_QUOTES

    STATUS.METADATA_CHANGED

    STATUS.IN_TRANS_READONLY

    EXT_FIELD_TYPE

    EXT_FIELD_TYPE.NONE

    EXT_FIELD_TYPE.JSON

    EXT_FIELD_TYPE.UUID

    EXT_FIELD_TYPE.INET4

    EXT_FIELD_TYPE.INET6

    EXT_FIELD_TYPE.POINT

    EXT_FIELD_TYPE.MULTIPOINT

    EXT_FIELD_TYPE.LINESTRING

    EXT_FIELD_TYPE.MULTILINESTRING

    EXT_FIELD_TYPE.POLYGON

    EXT_FIELD_TYPE.MULTIPOLYGON

    EXT_FIELD_TYPE.GEOMETRYCOLLECTION

    SESSION_TRACK

    spinner
    URI Connection (recommended):

    Keyword Arguments:

    Connection parameters can also be provided as keyword arguments. The most common ones are:

    • host - Host name or IP address of the database server. Can be a comma-separated list of hosts for simple failover. Default: 'localhost'

    • port - Port number of the database server. Default: 3306

    • user, username - Username for authentication

    • password, passwd - Password for authentication

    • database, db - Default database (schema) to select when connecting

    • unix_socket - Path to a Unix socket file for local connections (used in place of TCP)

    • autocommit - Enable autocommit mode. Default: False

    • converter - Conversion dictionary mapping FIELD_TYPE values to conversion functions

    For the full list of accepted parameters — including SSL/TLS options, timeouts, prepared-statement caching, configuration file loading, the result format options (dictionary, named_tuple, native_object), and the parameters that only apply to the C extension — see The connection class.

    • reconnect (connection parameter) - Removed. Automatic reconnection is no longer supported; use connection pools or call conn.reconnect() manually.

    • cursor_type (cursor option) - Removed in the pure-Python implementation; use buffered=False instead. The C extension still accepts it.

    • prepared (cursor option) - Deprecated in favor of binary=True. It still works but emits a DeprecationWarning.

    For migration guidance, see the Migration Guide.

    Examples:

    Output:

    Since version 2.0

    Creates an asynchronous MariaDB Connection object for use with async/await. As with connect(), the first positional argument, when given, is a connection URI string.

    Usage:

    For detailed async usage, see Async/Await Support.

    Since version 2.0

    Creates a synchronous connection pool.

    Note: Connection pooling requires the mariadb[pool] package to be installed (the --pre flag is required while 2.0 is a Release Candidate):

    Usage:

    Keyword Arguments:

    • `min_size` (int) - Minimum number of connections in pool. Default: same as max_size

    • `max_size` (int) - Maximum number of connections in pool. Default: 10

    • `ping_threshold` (float) - Ping connections idle for more than this many seconds. Default: 0.25

    • **kwargs - Connection arguments as described in mariadb.connect() method

    For detailed pooling documentation, see Connection Pooling.

    Since version 2.0

    Creates an asynchronous connection pool for use with async/await.

    Note: Requires mariadb[pool] package.

    Usage:

    For detailed async pooling, see Async/Await Support.

    Constructs an object capable of holding a binary value.

    Constructs an object holding a date value.

    Constructs an object holding a date value from the given ticks value (number of seconds since the epoch). For more information see the documentation of the standard Python time module.

    Constructs an object holding a time value.

    Constructs an object holding a time value from the given ticks value (number of seconds since the epoch). For more information see the documentation of the standard Python time module.

    Constructs an object holding a datetime value.

    Constructs an object holding a datetime value from the given ticks value (number of seconds since the epoch). For more information see the documentation of the standard Python time module.

    String constant stating the supported DB API level. The value for mariadb is 2.0.

    Integer constant stating the level of thread safety. In version 2.0 the value is 3, meaning threads may share the module, connections, and cursors. In version 1.1 the value is 1, meaning threads may share the module but not connections.

    String constant stating the type of parameter marker. For mariadb the value is qmark. For compatibility reasons mariadb also supports the format and pyformat paramstyles with the limitation that they can’t be mixed inside a SQL statement.

    String constant stating the version of the used MariaDB Connector/C library.

    Since version 1.1.0

    Returns a version as an integer. In version 2.0 this is the version of MariaDB Connector/Python itself, in the format: MAJOR_VERSION * 10000 + MINOR_VERSION * 100 + PATCH_VERSION. In version 1.1 it is the version of the MariaDB Connector/C library in use, in the format: MAJOR_VERSION * 10000 + MINOR_VERSION * 1000 + PATCH_VERSION.

    Since version 1.1.0 Returns a version as a tuple. In version 2.0 this is the version of MariaDB Connector/Python itself and may include a release-stage suffix (for example (2, 0, 0, 'rc2')). In version 1.1 it is the version of the MariaDB Connector/C library, in the format: (MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION)

    Compliant to DB API 2.0 MariaDB Connector/C provides information about errors through the following exceptions:

    Exception raised for errors that are due to problems with the processed data like division by zero, numeric value out of range, etc.

    Exception raised for errors that are related to the database

    Exception raised for errors that are related to the database interface rather than the database itself

    Exception raised for important warnings like data truncations while inserting, etc

    Exception raised for errors related to ConnectionPool class.

    Exception raised for errors that are related to the database’s operation and not necessarily under the control of the programmer.

    Exception raised when the relational integrity of the database is affected, e.g. a foreign key check fails

    Exception raised when the database encounters an internal error, e.g. the cursor is not valid anymore

    Exception raised for programming errors, e.g. table not found or already exists, syntax error in the SQL statement

    Exception raised in case a method or database API was used which is not supported by the database

    MariaDB Connector/Python type objects are immutable sets for type settings and defined in DBAPI 2.0 (PEP-249).

    Example:

    Output:

    This type object is used to describe columns in a database that are string-based (e.g. CHAR1).

    This type object is used to describe (long) binary columns in a database (e.g. LONG, RAW, BLOBs).

    This type object is used to describe numeric columns in a database.

    This type object is used to describe date/time columns in a database.

    This type object is not supported in MariaDB Connector/Python and represents an empty set.

    Constructors

    Connection

    connect(*args, connectionclass=None, **kwargs)

    Changed Parameters in Version 2.0

    Async Connection

    asyncConnect(*args, connectionclass=None, **kwargs)

    Connection Pool

    create_pool(**kwargs)

    create_async_pool(**kwargs)

    Type constructors

    Binary()

    Date(year, month, day)

    DateFromTicks(ticks)

    Time(hour, minute, second)

    TimeFromTicks(ticks)

    Timestamp(year, month, day, hour, minute, second)

    TimestampFromTicks(ticks)

    Attributes

    apilevel

    threadsafety

    paramstyle

    mariadbapi_version

    client_version

    client_version_info

    Exceptions

    exception DataError

    exception DatabaseError

    exception InterfaceError

    exception Warning

    exception PoolError

    exception OperationalError

    exception IntegrityError

    exception InternalError

    exception ProgrammingError

    exception NotSupportedError

    Type objects

    STRING

    BINARY

    NUMBER

    DATETIME

    ROWID

    spinner
    cursor.callproc("my_storedprocedure", (1,"foo"))
    from mariadb.constants import *
    import mariadb
    from mariadb.constants import *
    
    # connection parameters
    conn_params= {
        "user" : "example_user",
        "password" : "GHbe_Su3B8",
        "host" : "localhost"
    }
    
    with mariadb.connect(**conn_params) as connection:
        # test if LOAD DATA LOCAL INFILE is supported
        if connection.server_capabilities & CAPABILITY.LOCAL_FILES:
            print("Server supports LOCAL INFILE")
    Server supports LOCAL INFILE
    import mariadb
    from mariadb.constants import *
    
    # connection parameters
    conn_params= {
        "user" : "example_user",
        "password" : "wrong_password",
        "host" : "localhost"
    }
    
    # try to establish a connection
    try:
        connection= mariadb.connect(**conn_params)
    except mariadb.OperationalError as Err:
        if Err.errno == ERR.ER_ACCESS_DENIED_ERROR:
            print("Access denied. Wrong password!")
    Access denied. Wrong password!
    import mariadb
    from mariadb.constants import EXT_FIELD_TYPE
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    cursor = conn.cursor()
    
    cursor.execute("SELECT id, data, location FROM test_table")
    metadata = cursor.metadata
    
    if metadata:
        for i, ext_type in enumerate(metadata['ext_type_or_format']):
            if ext_type == EXT_FIELD_TYPE.JSON:
                print(f"Column {i} is JSON type")
            elif ext_type == EXT_FIELD_TYPE.UUID:
                print(f"Column {i} is UUID type")
            elif ext_type == EXT_FIELD_TYPE.POINT:
                print(f"Column {i} is POINT geometry type")
    
    cursor.close()
    conn.close()
    import mariadb
    
    # Simple URI
    conn = mariadb.connect("mariadb://user:password@localhost:3306/mydb")
    
    # URI with query parameters
    conn = mariadb.connect("mariadb://user:password@localhost/mydb?autocommit=true&binary=true")
    
    # Keyword arguments override URI values
    conn = mariadb.connect("mariadb://user:password@localhost/mydb", database="otherdb")
    import mariadb
    
    # URI connection (recommended)
    with mariadb.connect("mariadb://example_user:GHbe_Su3B8@localhost/test") as connection:
        print(connection.character_set)
    
    # Keyword arguments (still supported)
    with mariadb.connect(user="example_user", host="localhost", database="test", password="GHbe_Su3B8") as connection:
        print(connection.character_set)
    
    # Binary protocol enabled at connection level
    with mariadb.connect("mariadb://localhost/test?binary=true") as connection:
        cursor = connection.cursor()  # Uses binary protocol by default
        cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
    utf8mb4
    import asyncio
    import mariadb
    
    async def main():
        # URI connection
        conn = await mariadb.asyncConnect("mariadb://user:password@localhost/mydb")
        
        # Or with keyword arguments
        conn = await mariadb.asyncConnect(
            host="localhost",
            user="user",
            password="password",
            database="mydb"
        )
        
        cursor = await conn.cursor()
        await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
        row = await cursor.fetchone()
        
        await cursor.close()
        await conn.close()
    
    asyncio.run(main())
    pip install --pre mariadb[pool]
    import mariadb
    
    pool = mariadb.create_pool(
        host="localhost",
        user="user",
        password="password",
        database="mydb",
        min_size=5,
        max_size=20
    )
    
    with pool.acquire() as conn:
        with conn.cursor() as cursor:
            cursor.execute("SELECT 1")
    import asyncio
    import mariadb
    
    async def main():
        pool = await mariadb.create_async_pool(
            host="localhost",
            user="user",
            password="password",
            database="mydb",
            min_size=10,
            max_size=50
        )
        
        async with await pool.acquire() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("SELECT 1")
        
        await pool.close()
    
    asyncio.run(main())
    import mariadb
    from mariadb.constants import FIELD_TYPE
    
    print(FIELD_TYPE.GEOMETRY == mariadb.BINARY)
    print(FIELD_TYPE.DATE == mariadb.DATE)
    print(FIELD_TYPE.VARCHAR == mariadb.BINARY)
    True
    True
    False
    method, which executes an
    statement to insert a new row into the table.
  • The update_account_amount() function updates the amount in an account associated with the given email.

  • The execute() method is called on the cursor in the update_account_amount() method, which executes an statement to update a row in the table.

  • In each of these functions, the query string is the first value specified to the execute() method.

  • In each of these functions, the new values for the row, and the values for the where clause if present, are specified to the execute() method using a tuple.

  • In each of these functions, the values in the tuple are substituted for the question marks (?) in the query string.

  • # Module Import
    import mariadb
    import sys
    
    # Adds account
    def add_account(cur, first_name, last_name, email, amount):
       """Adds the given account to the accounts table"""
    
       cur.execute("INSERT INTO test.accounts(first_name, last_name, email, amount) VALUES (?, ?, ?, ?)",
          (first_name, last_name, email, amount))
    
    # Update Last Name
    def update_account_amount(cur, email, change):
       """Updates amount of an account in the table"""
    
       cur.execute("UPDATE test.accounts SET amount=(amount-?) WHERE email=?",
             (change, email))
    
    # Instantiate Connection (Version 2.0 - URI connection)
    try:
       conn = mariadb.connect("mariadb://db_user:USER_PASSWORD@192.0.2.1:3306/test")
    
       cur = conn.cursor()
    
       new_account_fname = "John"
       new_account_lname = "Rockefeller"
       new_account_email = "john.rockefeller@example.com"
       new_account_amount = 418000000000.00
    
       add_account(cur,
          new_account_fname,
          new_account_lname,
          new_account_email,
          new_account_amount)
    
       new_account_change = 1000000.00
    
       update_account_amount(cur,
          new_account_email,
          new_account_change)
    
       conn.commit()
       conn.close()
    except Exception as e:
       print(f"Error committing transaction: {e}")
    
       conn.rollback()
    SELECT * from test.accounts;
    +----+------------+-------------+------------------------------+-----------------+
    | id | first_name | last_name   | email                        | amount          |
    +----+------------+-------------+------------------------------+-----------------+
    |  1 | John       | Rockefeller | john.rockefeller@example.com | 417999000000.00 |
    +----+------------+-------------+------------------------------+-----------------+
    try:
       # URI connection with autocommit
       conn = mariadb.connect("mariadb://db_user:USER_PASSWORD@192.0.2.1:3306/test?autocommit=true")
       
       # Or with keyword argument
       conn = mariadb.connect(
          host="192.0.2.1",
          port=3306,
          user="db_user",
          password="USER_PASSWORD",
          autocommit=True)
    
    except Exception as e:
         print(f"Connection Error: {e}")
    # Enable Auto-commit
    conn.autocommit = True
    import asyncio
    import mariadb
    
    async def async_transaction_example():
        """Demonstrates async transaction handling"""
        
        # Connect asynchronously
        conn = await mariadb.asyncConnect(
            "mariadb://db_user:USER_PASSWORD@192.0.2.1:3306/test"
        )
        
        try:
            cursor = conn.cursor()
            
            # Start transaction (autocommit is False by default)
            await cursor.execute(
                "INSERT INTO test.accounts(first_name, last_name, email, amount) VALUES (?, ?, ?, ?)",
                ("Jane", "Doe", "jane.doe@example.com", 50000.00)
            )
            
            await cursor.execute(
                "UPDATE test.accounts SET amount = amount - ? WHERE email = ?",
                (1000.00, "jane.doe@example.com")
            )
            
            # Commit transaction
            await conn.commit()
            print("Transaction committed successfully")
            
            await cursor.close()
        except mariadb.Error as e:
            # Rollback on error
            await conn.rollback()
            print(f"Transaction failed, rolled back: {e}")
        finally:
            await conn.close()
    
    # Run async function
    asyncio.run(async_transaction_example())
    import asyncio
    import mariadb
    
    async def transfer_funds(pool, from_email, to_email, amount):
        """Transfer funds between accounts using async pool"""
        
        async with await pool.acquire() as conn:
            try:
                async with conn.cursor() as cursor:
                    # Deduct from sender
                    await cursor.execute(
                        "UPDATE test.accounts SET amount = amount - ? WHERE email = ?",
                        (amount, from_email)
                    )
                    
                    # Add to receiver
                    await cursor.execute(
                        "UPDATE test.accounts SET amount = amount + ? WHERE email = ?",
                        (amount, to_email)
                    )
                    
                    # Commit transaction
                    await conn.commit()
                    print(f"Transferred {amount} from {from_email} to {to_email}")
            except mariadb.Error as e:
                # Rollback on error
                await conn.rollback()
                print(f"Transfer failed: {e}")
                raise
    
    async def main():
        # Create async pool
        pool = await mariadb.create_async_pool(
            "mariadb://db_user:USER_PASSWORD@192.0.2.1:3306/test",
            min_size=5,
            max_size=20
        )
        
        try:
            await transfer_funds(
                pool,
                "jane.doe@example.com",
                "john.rockefeller@example.com",
                1000.00
            )
        finally:
            await pool.close()
    
    asyncio.run(main())

    Transactions with MariaDB Connector/Python

    Code Example: Transactions

    Code Example: Enable Auto-commit

    Code Example: Async Transactions (New in 2.0)

    Async Transaction with Connection Pool

    ACID compliant
    Setup for Examples
    spinner

    MariaDB Connector/Python FAQ

    MariaDB Connector/Python FAQ addresses common installation issues, migration from 1.1 to 2.0, the binary vs text protocol distinction, async setup, and transaction commit requirements.

    This is a list of frequently asked questions about MariaDB Connector/Python. Feel free to suggest new entries!

    • - Connection parameters, methods, and attributes

    • - Cursor parameters, methods, and attributes

    Connection Pooling API - Pool configuration and usage

    The header files and libraries of the Python development package weren’t properly installed. Use your package manager to install them system-wide:

    Alpine (using apk):

    Ubuntu/Debian (using apt):

    CentOS/RHEL (using yum):

    Fedora (using dnf):

    MacOSX (using homebrew):

    OpenSuse (using zypper):

    Note: The python3 development packages of your distribution might not cover all minor versions of python3. If you are using python3.10 you may need to install python3.10-dev.

    Version 2.0 offers three installation options:

    1. Pure Python (default) - pip install --pre mariadb

      • Works everywhere, no compiler required

      • Good performance for most use cases

      • Recommended for development and testing

    2. Pre-compiled binary wheels - pip install --pre mariadb[binary]

      • Best for production

      • MariaDB Connector/C is bundled - no separate installation needed

    3. C extension from source - pip install --pre mariadb[c]

      • Requires MariaDB Connector/C 3.3.1+ to be pre-installed on your system

      • Maximum performance

    For connection pooling, add [pool] to any option:

    No, not anymore! This is a major change in version 2.0:

    • Pure Python (default): No MariaDB Connector/C required

    • Binary wheels (mariadb[binary]): No separate installation needed - MariaDB Connector/C is bundled inside the wheel

    • C extension from source (mariadb[c]): Yes, requires MariaDB Connector/C 3.3.1+ to be pre-installed on your system

    For most users, pip install --pre mariadb[binary,pool] provides the best experience with no external dependencies (the --pre flag is required while 2.0 is a Release Candidate).

    With deprecation of distutils (see PEP-632) version functions of distutils module were replaced in MariaDB Connector/Python 1.1.5 by packaging version functions.

    Before you can install MariaDB Connector/Python you have to install the packaging module:

    The previously installed version of MariaDB Connector/C is too old and cannot be used for the MariaDB Connector/Python version you are trying to install.

    To determine the installed version of MariaDB Connector/C, execute the command:

    • Check if your distribution can be upgraded to a more recent version of MariaDB Connector/C, which fits the requirements.

    • If your distribution doesn’t provide a recent version of MariaDB Connector/C, check the MariaDB Connector Download page, which provides latest versions for the major distributions.

    • If none of the above will work for you, build and install MariaDB Connector/C from source.

    The mariadb_config program is used to retrieve configuration information (such as the location of header files and libraries, installed version, etc.) from MariaDB Connector/C.

    This error indicates that MariaDB Connector/C, an important dependency for client/server communication that needs to be preinstalled, either was not installed or could not be found.

    • If MariaDB Connector/C was previously installed, the installation script cannot detect the location of mariadb_config. Locate the directory where mariadb_config was installed and add this directory to your PATH.

      # locate mariadb_config
      sudo find / -name "mariadb_config"
    • If MariaDB Connector/C was not installed and the location of mariadb_config couldn’t be detected, please install MariaDB Connector/C.

    Even if the correct version of MariaDB Connector/C was installed, there are multiple mysql.h include files installed on your system, either from libmysql or an older MariaDB Connector/C installation. This can be checked by executing:

    Open output.txt in your favourite editor and search for “search starts here” where you can see the include files and paths used for the build.

    If your distribution doesn’t provide a recent version of MariaDB Connector/C (required version is 3.3.1) you either can download a version of MariaDB Connector/C from the MariaDB Connector Download page or build the package from source:

    No. If an issue was fixed, the fix will be available in the next release via Python’s package manager repository (pypi.org).

    To build MariaDB Connector/Python from github sources, checkout latest sources from github:

    and build and install it with:

    1. Check if MariaDB server has been started.

    2. Check if the MariaDB server was correctly configured and uses the right socket file:

      mysqld --help --verbose | grep socket

      If the socket is different and cannot be changed, you can specify the socket in your connection parameters.

      connection = mariadb.connect(unix_socket="/path_socket/mysql.sock", ....)

      Another option is setting the environment variable MYSQL_UNIX_PORT.

      export MYSQL_UNIX_PORT=/path_to/mysql.sock

    See the comprehensive Migration Guide for detailed instructions. Key changes:

    1. Installation: pip install --pre mariadb[binary,pool] for best experience (the --pre flag is required while 2.0 is a Release Candidate)

    2. Remove deprecated parameters: reconnect, auto_reconnect, cursor_type, prepared

    3. Update cursor creation: Use binary=True instead of prepared=True

    4. Update pooling: Install mariadb[pool] and use create_pool() instead of ConnectionPool()

    5. Consider URI connections: mariadb.connect("mariadb://user:pass@host/db")

    Automatic reconnection was removed in version 2.0 because it:

    • Silently hid connection failures

    • Lost session state and uncommitted transactions

    • Broke transaction isolation guarantees

    Migration: Use connection pools (recommended) or call conn.reconnect() manually when needed.

    Version 2.0 introduces native async support:

    For connection pools:

    See Async/Await Support for detailed documentation.

    Both prepared and binary already existed as separate cursor options in version 1.1. In version 2.0, prepared is deprecated in favor of binary; passing prepared still works but emits a DeprecationWarning:

    Version 1.1 (either option):

    Version 2.0 (use binary):

    Both use the MariaDB binary protocol (prepared statements).

    Text protocol (default):

    • Predictable behavior

    • Good for ad-hoc queries

    • No preparation overhead

    Binary protocol (binary=True):

    • Better performance for repeated queries

    • Automatic prepared statement caching

    • Recommended for hot paths

    Enable at connection level for applications that mostly use parameterized queries:

    MariaDB Connector/Python uses MariaDB Connector/C for client-server communication (C extension only). The pure Python implementation supports standard authentication methods. All authentication plugins shipped together with MariaDB Connector/C can be used for user authentication in the C extension.

    Executing multiple statements in a single cursor.execute() call is not supported.

    Python versions which reached their end of life are not officially supported. While MariaDB Connector/Python might still work with older Python 3.x versions, it doesn’t work with Python version 2.x.

    No, there is no mogrify() method. Before a statement is executed, parameter markers other than question marks are rewritten to question marks; the statement and its data are then sent separately to the server, so the parameter values are not substituted into the SQL string on the client side.

    Example:

    Please note, that there is no need to escape ‘%s’ by ‘%%s’ for the time conversion in DATE_FORMAT() function.

    The default paramstyle (see PEP-249) is qmark (question mark) for parameter markers. For compatibility with other drivers MariaDB Connector/Python also supports (and automatically recognizes) the format and pyformat parameter styles.

    Mixing different paramstyles within the same query is not supported and will raise an exception.

    Default for autocommit in MariaDB Connector/Python is off, which means every transaction must be committed. Uncommitted pending transactions are rolled back automatically when the connection is closed.

    MariaDB Connector/Python FAQ

    API Reference

    Connection API
    Cursor API
    sudo apk add python3-dev
    sudo apt-get install python3-dev
    sudo yum install python3-devel
    sudo dnf install python3-devel
    brew install mariadb-connector-c
    sudo zypper in python3-devel
    pip install --pre mariadb[binary,pool]
    pip3 install packaging
    mariadb_config --cc_version
    export CFLAGS="-V -E"
    pip3 install mariadb > output.txt
    mkdir bld
    cd bld
    cmake ..
    make
    make install
    git clone https://github.com/mariadb-corporation/mariadb-connector-python.git
    python3 setup.py build
    python3 -m pip install .
    import asyncio
    import mariadb
    
    async def main():
        conn = await mariadb.asyncConnect("mariadb://user:pass@host/db")
        cursor = conn.cursor()
        await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
        row = await cursor.fetchone()
        await cursor.close()
        await conn.close()
    
    asyncio.run(main())
    pool = await mariadb.create_async_pool(
        "mariadb://user:pass@host/db",
        min_size=5,
        max_size=20
    )
    cursor = conn.cursor(binary=True)
    cursor = conn.cursor(binary=True)
    conn = mariadb.connect("mariadb://host/db?binary=true")
    data = ("Future", 2000)
    statement = """SELECT DATE_FORMAT(creation_time, '%h:%m:%s') as time, topic, amount
                   FROM mytable WHERE topic=%s and id > %s"""
    cursor.execute(statement, data)
    print(cursor.statement)
    SELECT DATE_FORMAT(creation_time, '%h:%m:%s') as time, topic, amount FROM mytable WHERE topic=? and id > ?
    .. code-block:: python
    
       with mariadb.connect(**conn_params) as conn:
           with conn.cursor() as cursor:
               cursor.execute("CREATE TABLE t1 (id int, name varchar(20))")
    
               # insert
               data = [(1, "Andy"), (2, "George"), (3, "Betty")]
               cursor.executemany("INSERT INTO t1 VALUES (?,?)", data)
    
               # commit pending transactions
               connection.commit()

    Installation

    Error: “Python.h: No such file or directory”

    Which installation option should I choose for version 2.0?

    Version 2.0 is currently a Release Candidate (RC); version 1.1 is the latest stable (GA) release. The 2.0 commands below use the --pre flag because pip otherwise installs the latest stable release (1.1). Do not use non-stable (non-GA) releases in production.

    Do I need MariaDB Connector/C for version 2.0?

    ModuleNotFoundError: No module named ‘packaging’

    MariaDB Connector/Python requires MariaDB Connector/C >= 3.3.1, found version 3.1.2

    OSError: mariadb_config not found

    Error: struct st_mariadb_methods’ has no member named ‘db_execute_generate_request’

    Q: My distribution doesn’t provide a recent version of MariaDB Connector/C

    Q: Does MariaDB Connector/Python provide pre-releases or snapshot builds which contain recent bug fixes?

    Q: How can I build an actual version from github sources?

    Connecting

    mariadb.OperationalError: Can’t connect to local server through socket ‘/tmp/mysql.sock’

    How do I migrate from version 1.1 to 2.0?

    What happened to auto_reconnect?

    How do I use async/await with version 2.0?

    What's the difference between prepared and binary?

    Should I use text or binary protocol?

    Q: Which authentication methods are supported by MariaDB Connector/Python?

    General

    Q: How do I execute multiple statements with cursor.execute()?

    Q: Does MariaDB Connector/Python work with Python 2.x?

    Q: How can I see a transformed statement? Is there a mogrify() method available?

    Q: Does MariaDB Connector/Python support paramstyle “pyformat”?

    Transactions

    Q: Previously inserted records disappeared after my program finished

    spinner

    Migration Guide: 1.1 to 2.0

    MariaDB Connector/Python 2.0 migration covers renamed parameters, removed auto-reconnect, updated pooling, URI connections, async/await support, and a migration checklist.

    This guide helps you migrate your applications from MariaDB Connector/Python 1.1 to version 2.0.0.

    Version 2.0 is currently a Release Candidate (RC); version 1.1 is the latest stable (GA) release. Until 2.0 reaches GA, install it with the --pre flag (for example pip install --pre mariadb); a plain pip install mariadb installs the latest stable release (1.1). Do not use non-stable (non-GA) releases in production.

    API Reference

    • Connection API - Connection parameters, methods, and attributes

    • Cursor API - Cursor parameters, methods, and attributes

    • - Pool configuration and usage

    Version 2.0 is a major rewrite that introduces significant improvements and breaking changes:

    • Flexible distribution options: Pure Python, C extension, and pre-compiled binary wheels

    • Native async/await support: First-class asynchronous API

    • URI connection strings: Standard mariadb:// connection syntax

    This always installed the C extension and required MariaDB Connector/C to be pre-installed.

    Version 2.0 is still a Release Candidate, so the --pre flag is required; without it, pip installs the latest GA release (1.1).

    Pure Python (default, works everywhere):

    C extension (maximum performance):

    Requires MariaDB Connector/C to be pre-installed on your system.

    Pre-compiled binary wheels (no local C connector required):

    MariaDB Connector/C is bundled - no separate installation needed.

    With connection pooling:

    • Pure Python is now default: No compiler or MariaDB Connector/C required

    • Connection pooling is optional: Must explicitly install mariadb[pool]

    • Binary wheels available: Pre-compiled for common platforms with MariaDB Connector/C bundled

    Version 1.1:

    Version 2.0:

    Why removed: Auto-reconnect silently hid failures, caused unpredictable behavior with lost session state, uncommitted transactions, and broken transaction isolation.

    Migration: Use connection pools instead. For manual reconnection, call conn.reconnect() explicitly.

    Version 1.1:

    Version 2.0:

    Migration: Replace cursor_type=CURSOR.READ_ONLY with buffered=False.

    Note: cursor_type is removed only in the pure-Python implementation. The C extension still accepts it.

    The binary cursor option already existed in version 1.1 alongside prepared. In version 2.0, prepared is deprecated in favor of binary; it still works but emits a DeprecationWarning.

    Version 1.1 (either option):

    Version 2.0 (use binary):

    Migration: Replace prepared=True with binary=True.

    Version 1.1: Automatically promoted certain parameter types (bytes, datetime) to binary protocol, even when not requested.

    Version 2.0:

    • Text protocol by default: Predictable, debuggable

    • Explicit binary=True required: No automatic promotion

    • Dict parameters always use text protocol: Named parameter substitution

    Version 1.1 (automatic promotion):

    Version 2.0 (explicit control):

    Migration: If you relied on automatic binary protocol, explicitly set binary=True.

    Version 1.1:

    Version 2.0:

    Migration:

    1. Install mariadb[pool]

    2. Use create_pool() instead of ConnectionPool()

    3. Note: pool_size

    Version 1.1:

    Version 2.0:

    Migration: The C extension still supports plugin_dir. Pure Python does not load native authentication plugins from disk.

    Version 2.0 introduces standard URI syntax:

    Migration: Consider using URI strings for cleaner configuration, especially with environment variables:

    New in 2.0 - Native asynchronous API:

    Migration: For async applications (FastAPI, Starlette, etc.), use the async API instead of wrapping synchronous calls in thread pools.

    Version 2.0 allows setting binary protocol at connection level:

    Migration: For applications that mostly use prepared statements, set binary=True at connection level.

    New in 2.0 - Shared statement cache (opt-in):

    Benefits:

    • First execution pays PREPARE cost

    • Subsequent executions reuse prepared statement

    • 2-4× performance improvement for repeated queries

    Migration: No changes needed - caching is automatic. Consider increasing prep_stmt_cache_size for applications with many distinct queries.

    Before:

    After:

    Before:

    After:

    Version 2.0 introduces automatic prepared statement caching. For best performance:

    1. Use binary protocol for hot paths:

    2. Increase cache size for many distinct queries:

    3. Reuse the same SQL statements - the cache benefits repeated executions

    • Connection-level: When most queries are parameterized and repeated

    • Per-cursor: For specific hot queries in mixed workloads

    • Text protocol: For ad-hoc queries, SHOW commands, administrative queries

    For web applications with high concurrency (FastAPI, Starlette):

    • Version 1.1: Python 3.8 and later

    • Version 2.0: Python 3.10 and later

    Both versions support:

    • MariaDB Server 10.3+

    • MySQL Server 5.7+

    The mariadb.connect() API with keyword arguments remains largely backward compatible. Most 1.1 code will work with minimal changes after removing deprecated parameters.

    Maximum performance without compilation

  • No compiler required

  • Requires C compiler for building

  • For custom builds or platforms without binary wheels

  • Full type hints: Complete mypy and pyright compatibility

  • Improved performance: Faster parameter binding and prepared statement caching

  • Unified protocol control: Explicit binary vs text protocol selection

  • C extension requires pre-installation: MariaDB Connector/C must be installed separately when building from source with mariadb[c]

    split into
    min_size
    and
    max_size

    Overview

    Installation Changes

    Version 1.1 Installation

    Version 2.0 Installation Options

    Key Changes

    Breaking Changes

    1. Removed: Auto-Reconnect

    2. Removed: cursor_type Parameter

    3. Deprecated: prepared (use binary)

    4. Changed: Binary Protocol Behavior

    5. Connection Pooling Now Separate Package

    6. Removed: plugin_dir in Pure Python

    New Features

    1. URI Connection Strings

    2. Async/Await Support

    3. Connection-Level Binary Protocol

    4. Prepared Statement Caching

    Migration Checklist

    Step 1: Update Installation

    Step 2: Update Cursor Creation

    Step 3: Remove Auto-Reconnect Logic

    Performance Considerations

    Prepared Statement Caching

    When to Use Binary Protocol

    Async for High Concurrency

    Compatibility Notes

    Python Version Support

    Server Compatibility

    API Compatibility

    Connection Pooling API
    spinner
    pip install mariadb
    pip install --pre mariadb
    pip install --pre mariadb[c]
    pip install --pre mariadb[binary]
    pip install --pre mariadb[pool]
    # or combined
    pip install --pre mariadb[binary,pool]
    conn = mariadb.connect(
        host="localhost",
        user="root",
        password="secret",
        reconnect=True  # Automatic reconnection
    )
    # reconnect parameter removed
    conn = mariadb.connect(
        host="localhost",
        user="root",
        password="secret"
    )
    
    # Manual reconnection still available
    try:
        conn.ping()
    except mariadb.Error:
        conn.reconnect()  # Explicit reconnection only
    cursor = conn.cursor(cursor_type=mariadb.CURSOR.READ_ONLY)
    # Use buffered=False instead
    cursor = conn.cursor(buffered=False)
    cursor = conn.cursor(binary=True)
    cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
    cursor = conn.cursor(binary=True)
    cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
    cursor.execute("SELECT ?", (b'\xde\xad',))
    # Silently used binary protocol
    # Text protocol (default)
    cursor.execute("SELECT ?", (b'\xde\xad',))
    # Sends: SELECT _binary'\xde\xad'
    
    # Binary protocol (explicit)
    cursor = conn.cursor(binary=True)
    cursor.execute("SELECT ?", (b'\xde\xad',))
    # Uses COM_STMT_PREPARE + COM_STMT_EXECUTE
    import mariadb
    
    pool = mariadb.ConnectionPool(
        pool_name="mypool",
        pool_size=5,
        host="localhost",
        user="root",
        password="secret"
    )
    # First install pooling support (--pre is required while 2.0 is an RC)
    pip install --pre mariadb[pool]
    import mariadb
    
    # Synchronous pool
    pool = mariadb.create_pool(
        host="localhost",
        user="root",
        password="secret",
        min_size=5,
        max_size=10
    )
    
    # Asynchronous pool (new in 2.0)
    pool = await mariadb.create_async_pool(
        host="localhost",
        user="root",
        password="secret",
        min_size=5,
        max_size=10
    )
    conn = mariadb.connect(
        host="localhost",
        plugin_dir="/path/to/plugins"
    )
    # plugin_dir removed in pure Python implementation
    # Still available in C extension
    conn = mariadb.connect(host="localhost")
    # Simple connection
    conn = mariadb.connect("mariadb://root:secret@localhost:3306/mydb")
    
    # With query parameters
    conn = mariadb.connect(
        "mariadb://root:secret@localhost:3306/mydb?binary=true&autocommit=true"
    )
    
    # Keyword arguments override URI values
    conn = mariadb.connect(
        "mariadb://root:secret@localhost/mydb",
        database="otherdb"  # Overrides 'mydb'
    )
    import os
    
    DATABASE_URL = os.getenv("DATABASE_URL")
    conn = mariadb.connect(DATABASE_URL)
    import asyncio
    import mariadb
    
    async def main():
        # Single connection
        async with await mariadb.asyncConnect(
            "mariadb://user:pass@host/db"
        ) as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
                row = await cursor.fetchone()
                print(row)
    
        # Connection pool
        pool = await mariadb.create_async_pool(
            "mariadb://user:pass@host/db",
            min_size=5,
            max_size=20
        )
        
        async with await pool.acquire() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("SELECT 1")
                result = await cursor.fetchone()
        
        await pool.close()
    
    asyncio.run(main())
    # All cursors default to binary protocol
    conn = mariadb.connect(
        "mariadb://localhost/mydb?binary=true"
    )
    
    # Or with keyword argument
    conn = mariadb.connect(
        host="localhost",
        database="mydb",
        binary=True
    )
    
    # All cursors now use binary protocol by default
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
    # The shared prepared-statement cache is disabled by default; enable it explicitly
    conn = mariadb.connect("mariadb://localhost/mydb?cache_prep_stmts=true")
    
    # Configure the cache size (applies when the cache is enabled)
    conn = mariadb.connect(
        "mariadb://localhost/mydb?cache_prep_stmts=true&prep_stmt_cache_size=500"
    )
    # Choose your installation option (--pre is required while 2.0 is an RC)
    pip install --pre mariadb[binary,pool]
    cursor = conn.cursor(prepared=True)
    cursor = conn.cursor(cursor_type=mariadb.CURSOR.READ_ONLY)
    cursor = conn.cursor(binary=True)
    cursor = conn.cursor(buffered=False)
    conn = mariadb.connect(
        host="localhost",
        reconnect=True
    )
    # Use connection pool (recommended)
    pool = mariadb.create_pool(
        host="localhost",
        min_size=5,
        max_size=10
    )
    
    # Or handle reconnection manually
    try:
        conn.ping()
    except mariadb.Error:
        conn.reconnect()
    conn = mariadb.connect("mariadb://localhost/mydb?binary=true")
    conn = mariadb.connect(
        "mariadb://localhost/mydb?prep_stmt_cache_size=500"
    )
    # Instead of thread pool wrapping
    pool = await mariadb.create_async_pool(
        "mariadb://localhost/mydb",
        min_size=10,
        max_size=50
    )

    Async/Await Support

    Async/await support in MariaDB Connector/Python 2.0 enables non-blocking database operations via asyncConnect, AsyncCursor, and create_async_pool for asyncio-based Python applications.

    MariaDB Connector/Python 2.0 introduces native async/await support for asynchronous database operations. This enables efficient database access in async applications like FastAPI, Starlette, and other asyncio-based frameworks.

    API Reference

    • Connection API - Connection parameters, methods, and attributes

    • Cursor API - Cursor parameters, methods, and attributes

    • - Pool configuration and usage

    The async API provides:

    • Native asyncio integration: No thread pool wrapping required

    • Async connections: asyncConnect() function and AsyncConnection class

    • Async cursors: AsyncCursor

    Both the pure Python and C extension implementations support async operations.

    Async connections support the same parameters as synchronous connections:

    Connection pools are essential for web applications handling multiple concurrent requests.

    Returns rows as dictionaries instead of tuples:

    Returns rows as named tuples:

    Fetches rows on demand instead of buffering entire result set:

    Use binary protocol for better performance with prepared statements:

    Always use connection pools in production:

    Enable for repeated queries (enabled by default):

    Use executemany() for bulk inserts:

    The async implementation provides:

    • No GIL contention: Pure Python async uses native asyncio I/O

    • Efficient concurrency: Handle thousands of concurrent connections

    • Lower latency: No thread pool overhead

    Note: Async excels in high-concurrency scenarios, not single-threaded throughput.

    1. Always use connection pools in production applications

    2. Use context managers for automatic resource cleanup

    3. Enable binary protocol for repeated parameterized queries

    class with async methods
  • Async connection pools: create_async_pool() for connection pooling

  • Context manager support: Async with statements for resource management

  • Same API surface: Familiar interface matching the synchronous API

  • Better resource usage: Event loop scheduling vs thread context switching
    Handle errors properly with try/except blocks
  • Close pools during application shutdown

  • Configure pool sizes based on your workload

  • Use prepared statement caching for better performance

  • Avoid creating connections per request - use pools instead

  • Overview

    Basic Async Connection

    Single Connection

    Using Context Managers (Recommended)

    Connection Parameters

    URI Connection

    Keyword Arguments

    Combining URI and Keywords

    Async Cursor Operations

    Executing Queries

    Fetching Results

    Inserting Data

    Batch Operations

    Async Transactions

    Async Connection Pools

    Creating an Async Pool

    Pool with URI

    Pool Configuration

    FastAPI Integration Example

    Error Handling

    Cursor Types

    Dictionary Cursor

    Named Tuple Cursor

    Unbuffered Cursor

    Binary Protocol with Async

    Performance Considerations

    Connection Pooling

    Prepared Statement Caching

    Batch Operations

    Async vs Sync Performance

    Complete Example

    Best Practices

    Migration from Sync to Async

    Before (Synchronous)

    After (Asynchronous)

    With Context Managers

    Connection Pooling API
    spinner
    import asyncio
    import mariadb
    
    async def main():
        # Connect using URI
        conn = await mariadb.asyncConnect("mariadb://user:password@localhost/mydb")
        
        try:
            cursor = conn.cursor()
            try:
                # Execute query
                await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
                
                # Fetch results
                row = await cursor.fetchone()
                print(row)
            finally:            
                await cursor.close()
        finally:
            await conn.close()
    
    asyncio.run(main())
    import asyncio
    import mariadb
    
    async def main():
        # Connection and cursor automatically closed
        async with await mariadb.asyncConnect(
            "mariadb://user:password@localhost/mydb"
        ) as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
                row = await cursor.fetchone()
                print(row)
    
    asyncio.run(main())
    conn = await mariadb.asyncConnect(
        "mariadb://user:password@localhost:3306/mydb?autocommit=true&binary=true"
    )
    conn = await mariadb.asyncConnect(
        host="localhost",
        port=3306,
        user="user",
        password="password",
        database="mydb",
        autocommit=True,
        binary=True
    )
    # Keywords override URI values
    conn = await mariadb.asyncConnect(
        "mariadb://user:password@localhost/mydb",
        database="otherdb"  # Overrides 'mydb'
    )
    async with await mariadb.asyncConnect("mariadb://localhost/mydb") as conn:
        async with conn.cursor() as cursor:
            # Simple query
            await cursor.execute("SELECT COUNT(*) FROM users")
            count = await cursor.fetchone()
            print(f"Total users: {count[0]}")
            
            # Parameterized query
            await cursor.execute(
                "SELECT name, email FROM users WHERE id = ?",
                (user_id,)
            )
            user = await cursor.fetchone()
    async with conn.cursor() as cursor:
        await cursor.execute("SELECT * FROM users")
        
        # Fetch one row
        row = await cursor.fetchone()
        
        # Fetch multiple rows
        rows = await cursor.fetchmany(10)
        
        # Fetch all remaining rows
        all_rows = await cursor.fetchall()
        
        # Iterate over results
        await cursor.execute("SELECT * FROM users")
        async for row in cursor:
            print(row)
    async with conn.cursor() as cursor:
        # Single insert
        await cursor.execute(
            "INSERT INTO users (name, email) VALUES (?, ?)",
            ("Alice", "alice@example.com")
        )
        await conn.commit()
        
        # Get last inserted ID
        print(f"Inserted user ID: {cursor.lastrowid}")
    async with conn.cursor() as cursor:
        data = [
            ("Alice", "alice@example.com"),
            ("Bob", "bob@example.com"),
            ("Charlie", "charlie@example.com")
        ]
        
        await cursor.executemany(
            "INSERT INTO users (name, email) VALUES (?, ?)",
            data
        )
        await conn.commit()
        print(f"Inserted {cursor.rowcount} rows")
    async with await mariadb.asyncConnect("mariadb://localhost/mydb") as conn:
        try:
            async with conn.cursor() as cursor:
                # Start transaction (autocommit is False by default)
                await cursor.execute(
                    "UPDATE accounts SET balance = balance - ? WHERE id = ?",
                    (100, 1)
                )
                await cursor.execute(
                    "UPDATE accounts SET balance = balance + ? WHERE id = ?",
                    (100, 2)
                )
                
                # Commit transaction
                await conn.commit()
        except mariadb.Error as e:
            # Rollback on error
            await conn.rollback()
            print(f"Transaction failed: {e}")
            raise
    import asyncio
    import mariadb
    
    async def main():
        # Create pool
        pool = await mariadb.create_async_pool(
            host="localhost",
            user="user",
            password="password",
            database="mydb",
            min_size=5,    # Minimum connections
            max_size=20,   # Maximum connections
            ping_threshold=0.25  # Ping if idle > 250ms
        )
        
        # Use pool
        async with await pool.acquire() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
                row = await cursor.fetchone()
                print(row)
        
        # Close pool when done
        await pool.close()
    
    asyncio.run(main())
    pool = await mariadb.create_async_pool(
        "mariadb://user:password@localhost/mydb",
        min_size=10,
        max_size=50
    )
    pool = await mariadb.create_async_pool(
        host="localhost",
        user="user",
        password="password",
        database="mydb",
        min_size=5,           # Minimum pool size
        max_size=20,          # Maximum pool size
        ping_threshold=0.25,  # Ping connections idle > 250ms
        binary=True,          # Use binary protocol by default
        autocommit=False      # Transaction mode
    )
    from fastapi import FastAPI, HTTPException
    from contextlib import asynccontextmanager
    import mariadb
    
    # Global pool variable
    pool = None
    
    @asynccontextmanager
    async def lifespan(app: FastAPI):
        # Startup: Create pool
        global pool
        pool = await mariadb.create_async_pool(
            "mariadb://user:password@localhost/mydb",
            min_size=10,
            max_size=50
        )
        yield
        # Shutdown: Close pool
        await pool.close()
    
    app = FastAPI(lifespan=lifespan)
    
    @app.get("/users/{user_id}")
    async def get_user(user_id: int):
        async with await pool.acquire() as conn:
            async with conn.cursor(dictionary=True) as cursor:
                await cursor.execute(
                    "SELECT id, name, email FROM users WHERE id = ?",
                    (user_id,)
                )
                user = await cursor.fetchone()
                
                if user is None:
                    raise HTTPException(status_code=404, detail="User not found")
                
                return user
    
    @app.post("/users")
    async def create_user(name: str, email: str):
        async with await pool.acquire() as conn:
            async with conn.cursor() as cursor:
                try:
                    await cursor.execute(
                        "INSERT INTO users (name, email) VALUES (?, ?)",
                        (name, email)
                    )
                    await conn.commit()
                    
                    return {
                        "id": cursor.lastrowid,
                        "name": name,
                        "email": email
                    }
                except mariadb.IntegrityError:
                    await conn.rollback()
                    raise HTTPException(
                        status_code=400,
                        detail="User with this email already exists"
                    )
    import asyncio
    import mariadb
    
    async def main():
        try:
            conn = await mariadb.asyncConnect(
                "mariadb://user:password@localhost/mydb"
            )
        except mariadb.Error as e:
            print(f"Connection error: {e}")
            return
        
        try:
            async with conn.cursor() as cursor:
                await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
                row = await cursor.fetchone()
        except mariadb.DatabaseError as e:
            print(f"Database error: {e}")
        except mariadb.ProgrammingError as e:
            print(f"Programming error: {e}")
        finally:
            await conn.close()
    
    asyncio.run(main())
    async with conn.cursor(dictionary=True) as cursor:
        await cursor.execute("SELECT id, name, email FROM users WHERE id = ?", (1,))
        user = await cursor.fetchone()
        print(user["name"])  # Access by column name
    async with conn.cursor(named_tuple=True) as cursor:
        await cursor.execute("SELECT id, name, email FROM users WHERE id = ?", (1,))
        user = await cursor.fetchone()
        print(user.name)  # Access as attribute
    async with conn.cursor(buffered=False) as cursor:
        await cursor.execute("SELECT * FROM large_table")
        
        # Fetch rows one at a time
        async for row in cursor:
            process_row(row)
            # Only one row in memory at a time
    # Connection-level binary protocol
    conn = await mariadb.asyncConnect(
        "mariadb://localhost/mydb?binary=true"
    )
    
    async with conn.cursor() as cursor:
        # All queries use binary protocol
        await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
        row = await cursor.fetchone()
    
    # Or per-cursor
    async with conn.cursor(binary=True) as cursor:
        await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
        row = await cursor.fetchone()
    # Good: Connection pool
    pool = await mariadb.create_async_pool(
        "mariadb://localhost/mydb",
        min_size=10,
        max_size=50
    )
    
    # Bad: Creating connections per request
    async def handle_request():
        conn = await mariadb.asyncConnect("mariadb://localhost/mydb")
        # ... use connection
        await conn.close()
    conn = await mariadb.asyncConnect(
        "mariadb://localhost/mydb?binary=true&prep_stmt_cache_size=150"
    )
    # Good: Batch insert
    await cursor.executemany(
        "INSERT INTO users (name, email) VALUES (?, ?)",
        data
    )
    
    # Bad: Loop with execute
    for name, email in data:
        await cursor.execute(
            "INSERT INTO users (name, email) VALUES (?, ?)",
            (name, email)
        )
    import asyncio
    import mariadb
    from typing import Optional
    
    async def setup_database():
        """Initialize database connection pool"""
        pool = await mariadb.create_async_pool(
            host="localhost",
            user="user",
            password="password",
            database="mydb",
            min_size=5,
            max_size=20,
            binary=True
        )
        return pool
    
    async def get_user(pool, user_id: int) -> Optional[dict]:
        """Fetch user by ID"""
        async with await pool.acquire() as conn:
            async with conn.cursor(dictionary=True) as cursor:
                await cursor.execute(
                    "SELECT id, name, email FROM users WHERE id = ?",
                    (user_id,)
                )
                return await cursor.fetchone()
    
    async def create_user(pool, name: str, email: str) -> int:
        """Create new user and return ID"""
        async with await pool.acquire() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute(
                    "INSERT INTO users (name, email) VALUES (?, ?)",
                    (name, email)
                )
                await conn.commit()
                return cursor.lastrowid
    
    async def update_user(pool, user_id: int, name: str, email: str) -> bool:
        """Update user information"""
        async with await pool.acquire() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute(
                    "UPDATE users SET name = ?, email = ? WHERE id = ?",
                    (name, email, user_id)
                )
                await conn.commit()
                return cursor.rowcount > 0
    
    async def delete_user(pool, user_id: int) -> bool:
        """Delete user by ID"""
        async with await pool.acquire() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute(
                    "DELETE FROM users WHERE id = ?",
                    (user_id,)
                )
                await conn.commit()
                return cursor.rowcount > 0
    
    async def main():
        # Setup
        pool = await setup_database()
        
        try:
            # Create user
            user_id = await create_user(pool, "Alice", "alice@example.com")
            print(f"Created user with ID: {user_id}")
            
            # Get user
            user = await get_user(pool, user_id)
            print(f"User: {user}")
            
            # Update user
            updated = await update_user(pool, user_id, "Alice Smith", "alice.smith@example.com")
            print(f"Updated: {updated}")
            
            # Delete user
            deleted = await delete_user(pool, user_id)
            print(f"Deleted: {deleted}")
            
        finally:
            # Cleanup
            await pool.close()
    
    if __name__ == "__main__":
        asyncio.run(main())
    import mariadb
    
    conn = mariadb.connect("mariadb://localhost/mydb")
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
    row = cursor.fetchone()
    cursor.close()
    conn.close()
    import asyncio
    import mariadb
    
    async def main():
        conn = await mariadb.asyncConnect("mariadb://localhost/mydb")
        cursor = conn.cursor()
        await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
        row = await cursor.fetchone()
        await cursor.close()
        await conn.close()
    
    asyncio.run(main())
    async def main():
        async with await mariadb.asyncConnect("mariadb://localhost/mydb") as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
                row = await cursor.fetchone()
    
    asyncio.run(main())

    The connection class

    MariaDB Connector/Python Connection class reference covers parameters, methods for commit and rollback, and read-only attributes for server version and TLS state.

    class Connection(*args, **kwargs)

    MariaDB Connector/Python Connection Object

    Handles the connection to a MariaDB or MySQL database server. It encapsulates a database session.

    Connections are created using the method mariadb.connect()

    Connection Parameters

    The mariadb.connect() function accepts the following parameters:

    Basic Connection Parameters

    • host (str) - Hostname or IP address of the database server. Can be a comma-separated list for failover support (requires libmariadb 3.3 or later when used with the C extension). Default: 'localhost'

    • port (int) - Port number of the database server. Default: 3306

    • user, username (str) - Username for authentication. Default: None

    • password, passwd (str) - Password for authentication. Default: None

    • database, db (str) - Database (schema) name to use. Default: None

    • unix_socket (str) - Path to the Unix socket file for local connections. When host is localhost and this parameter is not set, the connector auto-detects the Linux distribution (via /etc/os-release) and uses the same default socket path that libmariadb is compiled with on that distro: /run/mysqld/mysqld.sock on Debian, Ubuntu, Arch, and Alpine; /var/lib/mysql/mysql.sock on Fedora, RHEL, and CentOS; /run/mysql/mysql.sock

    • protocol - Force a specific transport protocol. Accepted values are a case-insensitive string or an integer:

      • 'DEFAULT' / 0 - connector chooses automatically (Unix socket for localhost when available, otherwise TCP)

    • connect_timeout (float) - Timeout in seconds for establishing the initial connection to the server. Default: 10.0

    • socket_timeout (float) - I/O timeout in seconds for socket operations (read and write). Primary timeout parameter for the pure-Python connector. Default: None

    • ssl, use_ssl (bool) - Enable SSL/TLS encryption. Default: True in version 2.0 (secure by default); False in the version 1.1 C extension

    • ssl_ca (

    • default_file (str) - Read connection options from a MariaDB/MySQL option file. Option files are read only if this parameter or default_group is set. Explicit connection arguments take precedence over option-file values. On Windows the file must be an .ini file. Default: None

      • None

    For a description of configuration file handling and accepted settings, see the chapter of the MariaDB Connector/C documentation.

    • autocommit (bool) - Enable autocommit mode. Default: False

    • read_only (bool) - Set connection to read-only mode. Default: False

    • binary (bool) - Use binary protocol (prepared statements) by default. Default: False

    • max_allowed_packet (int) - Maximum packet size in bytes. Default: 16777216 (16MB)

    The connection character set is fixed at utf8mb4 and is not configurable through a connection parameter.

    • named_tuple (bool) - Return rows as named tuples instead of regular tuples. Default: False

    • dictionary (bool) - Return rows as dictionaries instead of tuples. Default: False

    • converter (dict) - Custom type converter dictionary mapping field types to conversion functions. Default: None

    Since version 2.0

    The connector ships in three packaging variants — pure-Python, a binary wheel, and the C extension — and selects an implementation automatically at import time. Override the choice with the MARIADB_PYTHON_CONNECTOR environment variable:

    Value
    Implementation

    Parameters tagged (C extension only) in the lists above are honored only when the C extension implementation is in use. On the pure-Python path those parameters are accepted but ignored, with the exception of read_timeout and write_timeout which are mapped to socket_timeout.

    Basic connection with dictionary parameters:

    Connection with SSL/TLS:

    Connection with URI (since version 2.0):

    Connection with timeouts and compression:

    Connection with result format options:

    Connection with failover hosts:

    Creates a transaction ID object suitable for passing to the .tpc_*() methods of this connection.

    Parameters:

    • format_id: Format id. Default to value 0.

    • global_transaction_id: Global transaction qualifier, which must be unique. The maximum length of the global transaction id is limited to 64 characters.

    • branch_qualifier: Branch qualifier which represents a local transaction identifier. The maximum length of the branch qualifier is limited to 64 characters.

    Since version 1.0.1.

    Example:

    Start a new transaction which can be committed by .commit() method, or canceled by .rollback() method.

    Since version 1.1.0.

    Example:

    Commit any pending transaction to the database.

    Example:

    Changes the user and default database of the current connection

    Parameters: : - user: user name

    • password: password

    • database: name of default database

    In order to successfully change users a valid username and password parameters must be provided and that user must have sufficient permissions to access the desired database. If for any reason authorization fails an exception will be raised and the current user authentication will remain.

    Example:

    Close the connection now (rather than whenever ._del_() is called).

    The connection will be unusable from this point forward; an Error (or subclass) exception will be raised if any operation is attempted with the connection. The same applies to all cursor objects trying to use the connection.

    Note that closing a connection without committing the changes first will cause an implicit rollback to be performed.

    Example:

    Create a new cursor for executing queries.

    Parameters:

    • cursor_class (Optional[type]) - Optional custom cursor class (advanced usage)

    • **kwargs (Any) - Additional cursor parameters:

      • named_tuple

    Returns:

    • Cursor object

    Raises:

    • ProgrammingError - If connection is closed

    By default, fetch methods return result set values as tuples. Use dictionary=True or named_tuple=True to change the return format.

    Removed in version 2.0:

    • cursor_type - Use buffered=True for buffered results

    • prepared - Use binary=True instead

    • cursorclass - No longer supported as a parameter

    Examples:

    This function is designed to be executed by a user with the SUPER privilege and is used to dump server status information into the log for the MariaDB Server relating to the connection.

    Since version 1.1.2.

    Example:

    Returns a tuple representing the version of the connected server in the following format: (MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION)

    Parameters: statement: string

    This function is used to create a legal SQL string that you can use in an SQL statement. The given string is encoded to an escaped SQL string.

    Since version 1.0.5.

    Output:

    This function is used to ask the server to kill a database connection specified by the connection_id parameter.

    The connection id can be retrieved by SHOW PROCESSLIST SQL command.

    Note: This function requires the SUPER or CONNECTION ADMIN privilege.

    Example:

    Checks if the connection to the database server is still available.

    If auto reconnect was set to true, an attempt will be made to reconnect to the database server in case the connection was lost

    If the connection is not available an InterfaceError will be raised.

    Example:

    tries to reconnect to a server in case the connection died due to timeout or other errors. It uses the same credentials which were specified in connect() method.

    Example:

    Resets the current connection and clears session state and pending results. Open cursors will become invalid and cannot be used anymore.

    Example:

    Causes the database to roll back to the start of any pending transaction

    Closing a connection without committing the changes first will cause an implicit rollback to be performed. Note that rollback() will not work as expected if autocommit mode was set to True or the storage engine does not support transactions.”

    Gets the default database for the current connection.

    The default database can also be obtained or changed by database attribute.

    Since version 1.1.0.

    Example:

    Shows error, warning and note messages from last executed command.

    Example:

    Parameter: : xid: xid object which was created by .xid() method of connection : class

    Begins a TPC transaction with the given transaction ID xid.

    This method should be called outside a transaction (i.e., nothing may have been executed since the last .commit() or .rollback()). Furthermore, it is an error to call .commit() or .rollback() within the TPC transaction. A ProgrammingError is raised if the application calls .commit() or .rollback() during an active TPC transaction.

    Example:

    Optional parameter:

    • xid : xid object which was created by .xid() method of connection class.

    When called with no arguments, .tpc_commit() commits a TPC transaction previously prepared with .tpc_prepare().

    If .tpc_commit() is called prior to .tpc_prepare(), a single phase commit is performed. A transaction manager may choose to do this if only a single resource is participating in the global transaction. When called with a transaction ID xid, the database commits the given transaction. If an invalid transaction ID is provided, a ProgrammingError will be raised. This form should be called outside a transaction, and is intended for use in recovery.

    Example (Two-Phase Commit):

    Performs the first phase of a transaction started with .tpc_begin(). A ProgrammingError will be raised if this method was called outside a TPC transaction.

    After calling .tpc_prepare(), no statements can be executed until .tpc_commit() or .tpc_rollback() have been called.

    Example:

    Returns a list of pending transaction IDs suitable for use with tpc_commit(xid) or .tpc_rollback(xid).

    Example:

    Parameter: : xid: xid object which was created by .xid() method of connection : class

    Performs the first phase of a transaction started with .tpc_begin(). A ProgrammingError will be raised if this method outside a TPC transaction.

    After calling .tpc_prepare(), no statements can be executed until .tpc_commit() or .tpc_rollback() have been called.

    Example:

    removed in version 2.0

    (read/write)

    Enable or disable automatic reconnection to the server if the connection is found to have been lost.

    When enabled, client tries to reconnect to a database server in case the connection to a database server died due to timeout or other errors.

    (read/write)

    Toggles autocommit mode on or off for the current database connection.

    Autocommit mode only affects operations on transactional table types. Be aware that rollback() will not work if autocommit mode was switched on.

    By default, autocommit mode is set to False.

    (read-only)

    Client character set.

    For MariaDB Connector/Python, it is always utf8mb4.

    (read-only)

    Client capability flags.

    Since version 1.1.0.

    (read-only)

    Client character set collation

    (read-only)

    Id of current connection

    (read/write)

    Returns or sets the default database for the current connection. Assigning to this attribute switches the default database (issuing a USE statement).

    Since version 1.1.0.

    (read-only)

    Returns true if the connection is alive.

    A ping command will be sent to the server for this purpose, which means this function might fail if there are still non-processed pending result sets.

    Since version 1.1.0.

    (read-only)

    Server capability flags.

    Since version 1.1.0.

    (read-only)

    Extended server capability flags (only for MariaDB database servers).

    Since version 1.1.0.

    (read-only)

    Server version in alphanumerical format (str)

    (read-only)

    Returns True if the connected server is MariaDB, False if it's MySQL.

    This property is useful for detecting server type and implementing server-specific logic.

    Example:

    (read-only)

    Returns the server name.

    (read-only)

    Database server TCP/IP port. This value will be 0 in case of an unix socket connection.

    (read-only)

    Return server status flags

    Since version 1.1.0.

    (read-only)

    Returns an integer representing the server version.

    The form of the version number is VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH

    (read-only)

    Returns numeric version of connected database server in tuple format.

    (read-only)

    Returns the TLS cipher suite in use.

    Since version 1.0.5.

    (read-only)

    Returns the TLS protocol version.

    (read-only)

    Returns peer certificate information for TLS connections.

    Since version 1.1.11.

    (read-only)

    Returns the unix socket file name.

    (read-only)

    Returns the username for the current connection or empty string if it can’t be determined, e.g., when using socket authentication.

    (read-only)

    Returns the number of warnings from the last executed statement., or zero if there are no warnings.

    The cursor class

    MariaDB Connector/Python Cursor class documents parameters, execute and fetch methods, and attributes such as rowcount, description, and sp_outparams for stored procedures.

    MariaDB Connector/Python Cursor Object

    Cursors are created using the connection.cursor() method and accept the following optional parameters:

    • buffered (bool) - Buffer all results immediately in memory. When True (default), all rows are fetched and stored in memory. When

    on openSUSE and SLES. On non-Linux platforms (Windows, macOS) or unknown distributions no auto-detection happens and the connection falls back to TCP.
    /tmp/mysql.sock
    is intentionally not probed (the
    /tmp
    directory is world-writable, which would allow a non-privileged attacker to plant a fake socket); pass
    unix_socket='/tmp/mysql.sock'
    explicitly if that path is required. Default:
    None
    'TCP' / 1 - force TCP/IP even when host is localhost
  • 'SOCKET' / 2 - force Unix socket (requires unix_socket to be set or auto-detected)

  • Default: 'DEFAULT'

    (no timeout; blocking)
  • query_timeout (int) - Maximum query execution time in seconds (0 means no timeout). Default: 0

  • read_timeout (C extension only) (float) - Read (receive) timeout in seconds, passed directly to libmariadb. On the pure-Python connector this value is accepted but mapped to socket_timeout. Default: same as socket_timeout

  • write_timeout (C extension only) (float) - Write (send) timeout in seconds, passed directly to libmariadb. On the pure-Python connector this value is accepted but mapped to socket_timeout. Default: same as socket_timeout

  • str
    ) - Path to Certificate Authority (CA) certificate file in PEM format. Default:
    None
  • ssl_cert (str) - Path to client certificate file in PEM format. Default: None

  • ssl_key (str) - Path to client private key file in PEM format. Default: None

  • ssl_capath (str) - Path to directory containing CA certificates in PEM format. Default: None

  • ssl_cipher (str) - List of permitted cipher suites for SSL/TLS. Default: None

  • ssl_crl (str) - Path to certificate revocation list file. Default: None

  • ssl_crlpath (str) - Path to directory containing CRL files. Default: None

  • ssl_verify_cert (bool) - Enable server certificate verification. Default: True in version 2.0; False in version 1.1

  • tls_version (str) - TLS version(s) to use (e.g., 'TLSv1.2', 'TLSv1.3', 'TLSv1.2,TLSv1.3'). Automatically enables SSL. Default: None

  • tls_fp (C extension only) (str) - SHA-256 fingerprint of the expected server certificate, used for certificate pinning. Default: None

  • tls_fp_list (C extension only) (str) - Path to a file containing a list of accepted server certificate SHA-256 fingerprints. Default: None

  • (the default) reads no option file.
  • A path reads only that file.

  • An empty string ("") reads the default option files instead: /etc, /etc/mysql, $MARIADB_HOME/$MYSQL_HOME, and ~/.my.cnf.

  • default_group (str) - An additional option-file group to read, on top of the always-read [client], [client-server], and [client-mariadb] groups. Setting it without default_file triggers reading of the default option files. Default: None

  • compress (bool) - Enable protocol compression. Default: False

  • local_infile (bool) - Enable LOAD DATA LOCAL INFILE statements. Default: None

  • init_command (str) - SQL command to execute when connecting and reconnecting. Default: None

  • plugin_dir (C extension only) (str) - Directory containing MariaDB client plugins. Not applicable to the pure-Python connector. Default: None

  • cache_prep_stmts (bool) - Enable the shared prepared-statement cache. Default: False

  • prep_stmt_cache_size (int) - Maximum number of cached prepared statements. Default: 100

  • pipeline (bool) - Enable pipelining for prepared statements. Default: True

  • client_flag (int) - Additional client capability flags. Default: 0

  • native_object (bool) - Return native Python objects for certain types. Default: False

    unset

    Default: try the C extension, then the binary wheel, fall back to pure-Python

    (
    bool
    ) - Return rows as named tuples
  • dictionary (bool) - Return rows as dictionaries

  • buffered (bool) - Buffer all results immediately

  • binary (bool) - Use binary protocol (prepared statements)

  • c / mariadb_c

    C extension (requires compilation, full feature set)

    binary / mariadb_binary

    Binary wheel (precompiled, bundled dependencies)

    python / mariadb

    Pure-Python implementation

    Timeout Parameters

    SSL/TLS Parameters

    Configuration File Parameters

    Connection Behavior Parameters

    Protocol and Performance Parameters

    Character Encoding

    Result Format Parameters

    Type Conversion Parameters

    Implementation Selection

    Connection Examples

    Connection constructors

    Connection.xid(format_id: int, global_transaction_id: str, branch_qualifier: str) -> Xid

    Connection methods

    Connection.begin() -> None

    Connection.commit() -> None

    Connection.change_user(user: Optional[str], password: Optional[str], database: Optional[str] = None) -> None

    Connection.close() -> None

    Connection.cursor(cursor_class: Optional[type] = None, **kwargs: Any) -> Cursor

    Connection.dump_debug_info() -> None

    Connection.get_server_version() -> tuple[int, int, int]

    Connection.escape_string(escape_str: str) -> str

    Connection.kill(connection_id: int) -> None

    Connection.ping() -> None

    Connection.reconnect() -> None

    Connection.reset() -> None

    Connection.rollback() -> None

    Connection.select_db(new_db: str) -> None

    Connection.show_warnings() -> Optional[List[tuple]]

    Connection.tpc_begin(xid: Xid) -> None

    Connection.tpc_commit(xid: Optional[Xid] = None) -> None

    Connection.tpc_prepare() -> None

    Connection.tpc_recover() -> List[tuple]

    Connection.tpc_rollback(xid: Optional[Xid] = None) -> None

    Connection attributes

    Connection.auto_reconnect: bool

    Connection.autocommit: bool

    Connection.character_set: str

    Connection.client_capabilities: int

    Connection.collation: str

    Connection.connection_id: int

    Connection.database: Optional[str]

    Connection.open: bool

    Connection.server_capabilities: int

    Connection.extended_server_capabilities: int

    Connection.server_info: str

    Connection.server_mariadb: bool

    Connection.server_name: Optional[str]

    Connection.server_port: int

    Connection.server_status: int

    Connection.server_version: int

    Connection.server_version_info: tuple

    Connection.tls_cipher: Optional[str]

    Connection.tls_version: Optional[str]

    Connection.tls_peer_cert_info: Optional[dict]

    Connection.unix_socket: Optional[str]

    Connection.user: Optional[str]

    Connection.warnings: int

    Configuration files
    spinner
    False
    , results are streamed from the server, reducing memory usage for large result sets. Default:
    True
  • named_tuple (bool) - Return rows as named tuples instead of regular tuples. Allows accessing columns by name (e.g., row.column_name). Default: False

  • dictionary (bool) - Return rows as dictionaries instead of tuples. Allows accessing columns by name (e.g., row['column_name']). Default: False

  • native_object (bool) - Return native Python objects for certain database types. Default: False. Available since version 2.0; passing it to cursor() in version 1.1 raises a TypeError.

    • binary (bool) - Use binary protocol (prepared statements) for this cursor. Overrides the connection-level binary setting. When True, uses COM_STMT_PREPARE + COM_STMT_EXECUTE for better performance with repeated queries. Default: Inherits from connection

    Basic cursor:

    Unbuffered cursor for large result sets:

    Dictionary cursor:

    Named tuple cursor:

    Binary protocol cursor:

    Combined parameters:

    Executes a stored procedure sp. The data sequence must contain an entry for each parameter the procedure expects.

    Input/Output or Output parameters have to be retrieved by .fetch methods, the .sp_outparams attribute indicates if the result set contains output parameters.

    Arguments: : - sp: Name of stored procedure.

    • data: Optional sequence containing data for placeholder : substitution.

    Example:

    Prepare and execute a SQL statement.

    Parameters may be provided as sequence or mapping and will be bound to variables in the operation. Variables are specified as question marks (paramstyle ='qmark'), however for compatibility reasons MariaDB Connector/Python also supports the 'format' and 'pyformat' paramstyles with the restriction, that different paramstyles can't be mixed within a statement.

    A reference to the operation will be retained by the cursor.

    Since version 2.0: If the cursor was created with binary=True, the statement uses the MariaDB binary protocol (prepared statements). With prepared statement caching enabled (default), the first execution prepares the statement and subsequent executions reuse the cached prepared statement for better performance.

    By default execute() method generates a buffered result unless the optional parameter buffered was set to False or the cursor was generated as an unbuffered cursor.

    Protocol Selection (Version 2.0):

    • Text protocol (default): Standard SQL execution, predictable behavior

    • Binary protocol (binary=True): Uses COM_STMT_PREPARE + COM_STMT_EXECUTE

    • Dict parameters: Always use text protocol for named parameter substitution

    Prepare a database operation (INSERT,UPDATE,REPLACE or DELETE statement) and execute it against all parameter found in sequence.

    Exactly behaves like .execute() but accepts a list of tuples, where each tuple represents data of a row within a table. .executemany() only supports DML (insert, update, delete) statements.

    If the SQL statement contains a RETURNING clause, executemany() returns a result set containing the values for columns listed in the RETURNING clause.

    Example:

    The following example will insert 3 rows:

    To insert special values like NULL or a column default, you need to specify indicators:

    • INDICATOR.NULL is used for NULL values

    • INDICATOR.IGNORE is used to skip update of a column.

    • INDICATOR.DEFAULT is used for a default value (insert/update)

    • INDICATOR.ROW is used to skip update/insert of the entire row.

    • All values for a column must have the same data type.

    • Indicators can only be used when connecting to a MariaDB Server 10.2 or newer. MySQL servers don’t support this feature.

    Fetch all remaining rows of a query result, returning them as a sequence of sequences (e.g. a list of tuples).

    An exception will be raised if the previous call to execute() didn't produce a result set or execute() wasn't called before.

    Example:

    Fetch the next set of rows of a query result, returning a sequence of sequences (e.g. a list of tuples). An empty sequence is returned when no more rows are available.

    The number of rows to fetch per call is specified by the parameter. If it is not given, the cursor's arraysize determines the number of rows to be fetched. The method should try to fetch as many rows as indicated by the size parameter. If this is not possible due to the specified number of rows not being available, fewer rows may be returned.

    An exception will be raised if the previous call to execute() didn't produce a result set or execute() wasn't called before.

    Example:

    Fetch the next row of a query result set, returning a single sequence, or None if no more data is available.

    An exception will be raised if the previous call to execute() didn't produce a result set or execute() wasn't called before.

    Example:

    Version 1.1 only. Return the next row from the currently executed SQL statement using the same semantics as .fetchone(). In version 2.0 this method was removed; iterate the cursor directly instead (for row in cursor:).

    Will make the cursor skip to the next available result set, discarding any remaining rows from the current set.

    Scroll the cursor in the result set to a new position according to mode.

    If mode is “relative” (default), value is taken as offset to the current position in the result set, if set to absolute, value states an absolute target position.

    Required by PEP-249. Does nothing in MariaDB Connector/Python

    Required by PEP-249. Does nothing in MariaDB Connector/Python

    (read/write)

    The number of rows to fetch at a time with .fetchmany().

    This read/write attribute defaults to 1 meaning to fetch a single row at a time.

    Example:

    (read-only)

    Controls whether result sets are buffered in memory or streamed from the server.

    Buffered (True, default):

    • All result rows are immediately fetched and stored in client memory

    • The entire result set is transferred at once

    • Connection is freed immediately after execute()

    • Multiple cursors can be active on the same connection

    • Higher memory usage for large result sets

    • Better for small to medium result sets

    Unbuffered (False):

    • Results are streamed row-by-row from the server

    • Only the current row is kept in memory

    • Connection remains blocked until all rows are fetched

    • Only one unbuffered cursor can be active per connection

    • Lower memory usage - ideal for large result sets

    • Must fetch all rows before executing another query on the same connection

    Example:

    Best Practices:

    Close the cursor and free resources. After closing, the cursor cannot be used anymore.

    Example:

    (read-only)

    Returns the reference to the connection object on which the cursor was created.

    Example:

    (read-only)

    This read-only attribute is a sequence of 11-item tuples. Each tuple contains information describing one result column:

    1. name - Column name

    2. type_code - Column type code

    3. display_size - Display size

    4. internal_size - Internal size

    5. precision - Precision

    6. scale - Scale

    7. null_ok - Whether NULL values are allowed

    8. field_flags - Field flags (extension to PEP-249)

    9. table_name - Table name (extension to PEP-249)

    10. original_column_name - Original column name (extension to PEP-249)

    11. original_table_name - Original table name (extension to PEP-249)

    This attribute will be None for operations that do not return rows or if the cursor has not had an operation invoked via the .execute*() method yet.

    Example:

    Checking BLOB vs TEXT fields:

    Returns the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute or the value for the last usage of LAST_INSERT_ID().

    If the last query wasn’t an INSERT or UPDATE statement or if the modified table does not have a column with the AUTO_INCREMENT attribute and LAST_INSERT_ID was not used, the returned value will be None

    (read-only)

    Similar to the description property, this property returns a dictionary with complete metadata for all columns in the result set.

    Each dictionary key contains a list of values, one for each column in the result set.

    Dictionary Keys:

    • catalog - Catalog name (always 'def')

    • schema - Current schema/database name

    • field - Column alias name, or original column name if no alias

    • org_field - Original column name

    • table - Table alias name, or original table name if no alias

    • org_table - Original table name

    • type - Column type (values from mariadb.constants.FIELD_TYPE)

    • charset - Numeric character set (collation) ID of the column

    • length - Maximum length of the column

    • max_length - Maximum length of the column (in version 2.0 this mirrors length)

    • decimals - Number of decimals for numeric types

    • flags - Field flags (values from mariadb.constants.FIELD_FLAG)

    • ext_type_or_format - Extended data type (values from mariadb.constants.EXT_FIELD_TYPE)

    Since version 1.1.8

    Example:

    Detecting Extended Types (JSON, UUID, INET, Geometry):

    (read-only)

    Indicates if the current result set contains OUT or INOUT parameters from a previously executed stored procedure.

    When calling a stored procedure with OUT or INOUT parameters using callproc() or execute(), the output parameters are returned as a separate result set. This attribute is True when the current result set contains these output parameters, and False otherwise.

    Example:

    Example with Multiple Result Sets:

    Using with Binary Protocol:

    (read-only)

    Returns the number of rows that the last execute*() method produced (for DQL statements like SELECT) or affected (for DML statements like UPDATE, INSERT, DELETE).

    Return Values:

    • Positive number - Number of rows returned (SELECT) or affected (INSERT/UPDATE/DELETE)

    • -1 - No execute*() has been performed, or rowcount cannot be determined

    • 0 - Statement executed but no rows were affected/returned

    Important Notes:

    • For unbuffered cursors, the exact row count is only available after all rows have been fetched

    • For buffered cursors, the row count is immediately available after execute()

    • For INSERT/UPDATE/DELETE, the row count is always immediately available

    Examples:

    Unbuffered Cursor:

    Buffered Cursor:

    DML Statements (INSERT/UPDATE/DELETE):

    Batch Operations with executemany():

    Practical Use Case - Verify Operation Success:

    (read-only)

    Version 1.1 only. Returns the last SQL statement that was executed by the cursor. This attribute is not available in version 2.0.

    Example:

    (read-only)

    Returns the number of warnings from the last executed statement, or zero if there are no warnings.

    Note: Detailed warning messages can be retrieved using the connection.show_warnings() method.

    Example:

    (read-only)

    Returns the current 0-based index of the cursor in the result set, or None if no result set is available.

    This property tracks the position within the current result set as rows are fetched.

    Example:

    (read-only)

    Returns the number of columns in the current result set, or 0 if there is no result set.

    Example:

    (read-only)

    Returns True if the cursor is closed, False otherwise.

    A cursor is considered closed if either the cursor itself was closed or the parent connection was closed.

    Example:

    Connection closure also closes cursors:

    Cursor Parameters

    Result Format Parameters

    Protocol Parameters

    Cursor Examples

    Cursor methods

    Cursor.callproc(sp: str, data: Sequence[Any] = ()) -> None

    Cursor.execute(sql: str, data: Optional[Union[Sequence[Any], dict]] = None, buffered: Optional[bool] = None) -> None

    Cursor.executemany(sql: str, data: Sequence[Union[Sequence[Any], dict]], buffered: Optional[bool] = None) -> None

    NOTE

    Cursor.fetchall() -> List[Any]

    Cursor.fetchmany(size: Optional[int] = None) -> List[Any]

    Cursor.fetchone() -> Optional[Any]

    Cursor.next() -> Optional[Any]

    Cursor.nextset() -> Optional[bool]

    Cursor.scroll(value: int, mode: str = 'relative') -> None

    Cursor.setinputsizes() -> None

    Cursor.setoutputsize() -> None

    Cursor attributes

    Cursor.arraysize: int

    Cursor.buffered: bool

    Cursor.close() -> None

    Cursor.connection: Connection

    Cursor.description: Optional[Sequence[Tuple]]

    Cursor.lastrowid

    Cursor.metadata: Optional[Dict[str, List]]

    Cursor.sp_outparams: bool

    Cursor.rowcount: int

    Cursor.statement: Optional[str]

    Cursor.warnings: int

    Cursor.rownumber: Optional[int]

    Cursor.field_count: int

    Cursor.closed: bool

    spinner
    import mariadb
    
    conn = mariadb.connect(
        host='localhost',
        port=3306,
        user='myuser',
        password='mypassword',
        database='mydb'
    )
    conn = mariadb.connect(
        host='localhost',
        user='myuser',
        password='mypassword',
        database='mydb',
        ssl_ca='/path/to/ca-cert.pem',
        ssl_cert='/path/to/client-cert.pem',
        ssl_key='/path/to/client-key.pem',
        ssl_verify_cert=True
    )
    # Basic URI
    conn = mariadb.connect("mariadb://myuser:mypassword@localhost:3306/mydb")
    
    # URI with SSL parameters
    conn = mariadb.connect(
        "mariadb://myuser:mypassword@localhost/mydb",
        ssl_ca='/path/to/ca-cert.pem',
        ssl_verify_cert=True
    )
    conn = mariadb.connect(
        host='localhost',
        user='myuser',
        password='mypassword',
        database='mydb',
        connect_timeout=5.0,
        socket_timeout=60.0,
        compress=True
    )
    # Return rows as dictionaries
    conn = mariadb.connect(
        host='localhost',
        user='myuser',
        password='mypassword',
        database='mydb',
        dictionary=True
    )
    
    cursor = conn.cursor()
    cursor.execute("SELECT id, name FROM users LIMIT 1")
    row = cursor.fetchone()
    print(row['name'])  # Access by column name
    # Multiple hosts for automatic failover
    conn = mariadb.connect(
        host='primary.example.com,secondary.example.com,tertiary.example.com',
        port=3306,
        user='myuser',
        password='mypassword',
        database='mydb'
    )
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    # Create a transaction ID for distributed transaction
    xid = conn.xid(1, "global_tx_12345", "branch_001")
    print(f"XID: {xid}")  # Output: (1, 'global_tx_12345', 'branch_001')
    
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    # Start explicit transaction
    conn.begin()
    
    cursor = conn.cursor()
    cursor.execute("INSERT INTO accounts (name, balance) VALUES (?, ?)", ("Alice", 1000))
    cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE name = ?", ("Alice",))
    
    # Commit the transaction
    conn.commit()
    
    cursor.close()
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    cursor = conn.cursor()
    
    try:
        cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", 
                       ("John Doe", "john@example.com"))
        cursor.execute("INSERT INTO logs (action) VALUES (?)", 
                       ("User created",))
        
        # Commit both inserts as a single transaction
        conn.commit()
        print("Transaction committed successfully")
    except mariadb.Error as e:
        # Rollback on error
        conn.rollback()
        print(f"Error: {e}")
    finally:
        cursor.close()
        conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    print(f"Current user: {conn.user}")
    print(f"Current database: {conn.database}")
    
    # Switch to a different user and database
    try:
        conn.change_user("app_user", "app_pass", "app_db")
        print(f"Changed to user: {conn.user}")
        print(f"Changed to database: {conn.database}")
    except mariadb.Error as e:
        print(f"Failed to change user: {e}")
    finally:
        conn.close()
    import mariadb
    
    # Using context manager (recommended - auto-closes)
    with mariadb.connect("mariadb://user:password@localhost/mydb") as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM users")
        users = cursor.fetchall()
        cursor.close()
    # Connection automatically closed here
    
    # Manual close
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    try:
        cursor = conn.cursor()
        cursor.execute("SELECT COUNT(*) FROM users")
        count = cursor.fetchone()[0]
        print(f"Total users: {count}")
    finally:
        conn.close()  # Always close in finally block
    # Default cursor (unbuffered, text protocol, returns tuples)
    cursor = conn.cursor()
    
    # Buffered cursor (stores entire result set in memory)
    cursor = conn.cursor(buffered=True)
    
    # Binary protocol cursor (prepared statements)
    cursor = conn.cursor(binary=True)
    
    # Dictionary cursor (access columns by name)
    cursor = conn.cursor(dictionary=True)
    row = cursor.fetchone()
    print(row['column_name'])
    
    # Named tuple cursor (access columns as attributes)
    cursor = conn.cursor(named_tuple=True)
    row = cursor.fetchone()
    print(row.column_name)
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    try:
        # Dump debug information to server log
        # Requires SUPER privilege
        conn.dump_debug_info()
        print("Debug info dumped to server log")
    except mariadb.Error as e:
        print(f"Error: {e}")
        # Output: Error: Access denied; you need (at least one of) the SUPER privilege(s)
    
    conn.close()
    # connection parameters
    conn_params= {
        "user" : "example_user",
        "password" : "GHbe_Su3B8",
        "host" : "localhost"
    }
    
    with mariadb.connect(**conn_params) as connection:
        string = 'This string contains the following special characters: \\,"'
        print(connection.escape_string(string))
    This string contains the following special characters: \\,\"
    import mariadb
    import time
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    cursor = conn.cursor()
    
    # Get list of active connections
    cursor.execute("SHOW PROCESSLIST")
    processes = cursor.fetchall()
    
    print("Active connections:")
    for proc in processes:
        conn_id, user, host, db, command, time_val, state, info = proc
        print(f"ID: {conn_id}, User: {user}, DB: {db}, Command: {command}")
    
    # Kill a specific connection (requires SUPER privilege)
    target_connection_id = 123
    try:
        conn.kill(target_connection_id)
        print(f"Connection {target_connection_id} killed successfully")
    except mariadb.Error as e:
        print(f"Error killing connection: {e}")
    
    cursor.close()
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    try:
        # Check if connection is alive
        conn.ping()
        print("Connection is alive")
    except mariadb.InterfaceError:
        print("Connection lost")
    finally:
        conn.close()
    import mariadb
    import time
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    try:
        cursor = conn.cursor()
        cursor.execute("SELECT 1")
        cursor.close()
        
        # Simulate connection timeout or network issue
        # In real scenario, connection might be lost
        
        # Reconnect with same credentials
        conn.reconnect()
        print("Reconnected successfully")
        
        cursor = conn.cursor()
        cursor.execute("SELECT 2")
        cursor.close()
        
    except mariadb.Error as e:
        print(f"Error: {e}")
    finally:
        conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    cursor = conn.cursor()
    
    # Set some session variables
    cursor.execute("SET @my_var = 100")
    cursor.execute("SELECT @my_var")
    print(cursor.fetchone())  # Output: (100,)
    
    # Reset connection - clears session state
    conn.reset()
    
    # Previous cursor is now invalid, create new one
    cursor = conn.cursor()
    cursor.execute("SELECT @my_var")
    print(cursor.fetchone())  # Output: (None,) - variable cleared
    
    cursor.close()
    conn.close()
    import mariadb
    
    conn = mariadb.connect(
        host="localhost",
        user="root",
        password="secret"
    )
    
    print(f"Current database: {conn.database}")  # Output: None
    
    # Select a database
    conn.select_db("mydb")
    print(f"Current database: {conn.database}")  # Output: mydb
    
    cursor = conn.cursor()
    cursor.execute("SELECT DATABASE()")
    print(cursor.fetchone())  # Output: ('mydb',)
    
    cursor.close()
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    cursor = conn.cursor()
    
    # Initially no warnings
    print(conn.show_warnings())  # Output: None
    
    # Generate a warning by inserting value out of range
    cursor.execute("SET session sql_mode=''")
    cursor.execute("CREATE TEMPORARY TABLE test_warn (a tinyint)")
    cursor.execute("INSERT INTO test_warn VALUES (300)")  # Value too large for tinyint
    
    # Get warnings
    warnings = conn.show_warnings()
    if warnings:
        for level, code, message in warnings:
            print(f"{level} ({code}): {message}")
        # Output: Warning (1264): Out of range value for column 'a' at row 1
    
    cursor.close()
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    # Create transaction ID
    xid = conn.xid(0, "global_tx_001", "branch_001")
    
    # Begin distributed transaction
    conn.tpc_begin(xid)
    
    cursor = conn.cursor()
    cursor.execute("INSERT INTO orders (product, quantity) VALUES (?, ?)", ("Widget", 10))
    cursor.close()
    
    # Single-phase commit (no prepare)
    conn.tpc_commit(xid)
    
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    # Create transaction ID
    xid = conn.xid(0, "global_tx_002", "branch_002")
    
    # Begin distributed transaction
    conn.tpc_begin(xid)
    
    cursor = conn.cursor()
    cursor.execute("UPDATE inventory SET quantity = quantity - 5 WHERE product = ?", ("Widget",))
    cursor.close()
    
    # Prepare transaction (phase 1)
    conn.tpc_prepare()
    
    # Commit transaction (phase 2)
    conn.tpc_commit()
    
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    xid = conn.xid(0, "global_tx_003", "branch_003")
    conn.tpc_begin(xid)
    
    cursor = conn.cursor()
    cursor.execute("INSERT INTO transactions (amount) VALUES (?)", (100.00,))
    cursor.close()
    
    # Prepare the transaction (phase 1 of 2PC)
    conn.tpc_prepare()
    
    # At this point, transaction is prepared but not committed
    # Can now commit or rollback
    conn.tpc_commit()
    
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    # Get list of pending prepared transactions
    pending_xids = conn.tpc_recover()
    
    if pending_xids:
        print(f"Found {len(pending_xids)} pending transactions")
        for xid_data in pending_xids:
            print(f"Pending XID: {xid_data}")
            # Can commit or rollback these transactions
            # xid = conn.xid(*xid_data)
            # conn.tpc_commit(xid)
    else:
        print("No pending transactions")
    
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    xid = conn.xid(0, "global_tx_004", "branch_004")
    conn.tpc_begin(xid)
    
    cursor = conn.cursor()
    try:
        cursor.execute("UPDATE accounts SET balance = balance - 1000 WHERE id = ?", (1,))
        cursor.execute("UPDATE accounts SET balance = balance + 1000 WHERE id = ?", (2,))
        
        # Check for errors
        cursor.execute("SELECT balance FROM accounts WHERE id = 1")
        balance = cursor.fetchone()[0]
        
        if balance < 0:
            # Rollback the distributed transaction
            conn.tpc_rollback()
            print("Transaction rolled back - insufficient funds")
        else:
            conn.tpc_prepare()
            conn.tpc_commit()
            print("Transaction committed")
            
    except mariadb.Error as e:
        conn.tpc_rollback()
        print(f"Error: {e}")
    finally:
        cursor.close()
        conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    
    if conn.server_mariadb:
        print("Connected to MariaDB server")
        print(f"Version: {conn.server_info}")
        # Use MariaDB-specific features
        cursor = conn.cursor()
        cursor.execute("SELECT JSON_DETAILED('{\"a\": 1}')")
    else:
        print("Connected to MySQL server")
        print(f"Version: {conn.server_info}")
        # Use MySQL-compatible features only
    
    conn.close()
    import mariadb
    
    conn = mariadb.connect("mariadb://user:password@localhost/mydb")
    cursor = conn.cursor()
    cursor.execute("SELECT id, name FROM users")
    for row in cursor:
        print(f"ID: {row[0]}, Name: {row[1]}")
    cursor.close()
    conn.close()