Table of Contents

PHP RFC: Add MariaDB-specific features to mysqlnd and mysqli

Introduction

The PHP MySQL ecosystem is currently centered around mysqlnd, mysqli, and PDO_MySQL, which together provide a unified and efficient interface for interacting with MySQL-compatible database servers. MariaDB originated as a fork of MySQL and continues to share a large portion of its protocol, behavior, and feature set. Because of this substantial overlap, maintaining a completely separate PHP extension for MariaDB would introduce unnecessary duplication, fragmentation, and long-term maintenance cost.

At the same time, MySQL and MariaDB have diverged over the years. MariaDB has introduced a number of server-side features that are not available in MySQL, many of which provide significant performance and observability improvements. Currently, these MariaDB-specific capabilities are either inaccessible or only partially usable from PHP, despite being available through the same wire protocol and client library functions.

This RFC proposes to extend mysqlnd and mysqli to optionally expose MariaDB-specific functionality when connected to a MariaDB server, without affecting behavior when used with MySQL. The goal is not to fork or specialize the extensions, but to enhance them in a way that preserves compatibility while allowing PHP applications to benefit from MariaDB’s additional capabilities.

The MariaDB features targeted by this proposal include:

Exposing these features through existing PHP database extensions allows developers to take advantage of MariaDB’s strengths while continuing to rely on familiar MySQL-oriented APIs. This approach aligns with PHP’s long-standing emphasis on pragmatism, performance, and backward compatibility, while preparing the extensions to handle protocol divergence and feature evolution in MariaDB.

Proposal

Notes:

Detecting MySQL or MariaDB

A fundamental requirement for exposing MariaDB-specific features in PHP extensions is reliably detecting whether the connected server is MariaDB or MySQL. This cannot be done solely by checking the server_version string. While standard MySQL and MariaDB installations report the server type and version in server_version, many derived products—including cloud offerings, packaged distributions, and proxies may report different names, modified version numbers, or other inconsistencies. Therefore, relying on server_version alone is unreliable for feature detection.

A robust approach is to determine server type through capability flags exchanged between the client and server during the connection handshake. These flags indicate which features the server supports and which extensions the client can enable.

One key difference between MySQL and MariaDB is the handling of the long password capability:

MySQL servers always indicate the CLIENT_LONG_PASSWORD capability.

MariaDB historically used the same capability name, but later versions renamed it to CLIENT_MYSQL and removed it entirely.

By examining these flags, the client can detect MariaDB servers accurately and safely. Once a MariaDB server is recognized, the client can both read and advertise MariaDB-specific capabilities, enabling access to enhanced features.

To fully support modern MariaDB features, PHP extensions must handle 64-bit capability flags. These flags extend the feature set beyond what can fit in traditional 32-bit integers. For legacy 32-bit clients and to maintain backward compatibility, it is necessary to expose these capabilities in both server_capabilities and ext_server_capabilities. This dual exposure ensures that extensions can access all advertised features safely, regardless of the client architecture.

The full protocol description for MariaDB capabilities can be found in the official documentation: MariaDB Client/Server Protocol.

This capability-based detection allows PHP extensions to:

Bulk Execution

MariaDB provides mechanisms to improve the performance of repeated or multi-row statements through bulk execution. The most common scenario is INSERT statements. In many cases, a standard single-row INSERT or REPLACE can be rewritten using the multi-value syntax:

 INSERT INTO table (col1, col2) VALUES (?, ?), (?, ?), ..., (?, ?) 

This approach can significantly reduce network round-trips and server parsing overhead. However, it has some limitations:

The MySQL protocol already anticipated support for bulk operations when prepared statements were introduced in MySQL 4.1. Prepared statement headers include a 4-byte iteration count, intended to allow repeated execution of a statement. This field, however, was never used by MySQL.

MariaDB addressed this limitation in version 10.2 by introducing a new command, COM_STMT_BULK_EXECUTE, which implements an enhanced protocol for executing bulk operations. This protocol provides several advantages:

From a PHP perspective, exposing bulk execution through mysqli or PDO would allow applications to take advantage of these performance gains without requiring changes to existing SQL logic, other than optionally preparing statements for bulk execution.

Example INSERT:

<?php
$stmt = $mysqli->prepare("INSERT INTO t1 (col1, col2) VALUES (?, ?)");
$rows = [ [1, 'a'], [2, 'b'], [3, 'c'], ];
$stmt->executemany($rows);
?>

Example UPDATE with indicator variable:

<?php
use Mysql\Indicator;
 
$stmt = $mysqli->prepare("UPDATE table t1 SET col2=? WHERE col1=?");
$rows = [
  ['b', 1],
  [Indicator::Default, 3]
];
$stmt->executemany($rows);
?>

Additional advantages of bulk execution include:

Prepared Statement Metadata Caching

When a prepared statement is created, the server normally returns statement metadata describing result columns. This metadata includes:

For applications that repeatedly execute identical SQL statements—common in request-based execution models—this metadata is typically transmitted and parsed repeatedly, even though it does not change.

MariaDB supports prepared statement metadata caching, allowing the client to indicate that it is capable of caching metadata locally. Once this capability is negotiated:

This optimization reduces:

Importantly, this does not change the logical protocol flow of prepared statements. Instead, it optimizes the existing flow by eliminating redundant metadata transfer when both client and server support caching. This improves performance transparently, without requiring changes to application code or SQL syntax.

Progress Indication

Long-running SQL statements such as large ALTER TABLE, CREATE INDEX or complex UPDATE operations can take a significant amount of time to complete. Traditionally, clients have no insight into the progress of such operations and can only wait for completion or timeout.

MariaDB provides server-side progress reporting, allowing the server to send progress information to the client while a statement is executing. This information includes:

Progress information is sent asynchronously during statement execution and does not alter the semantics of the SQL statement itself.

Key characteristics:

From a PHP perspective, exposing this feature allows applications to:

Example pseudo-code:

<?php
function callback_progress($current, $max) { 
  printf("Progress: %d / %d\n", $current, $max);
}
 
$mysqli->options(MYSQLI_OPT_PROGRESS_CALLBACK, 'callback_progress');
$mysqli->query("ALTER TABLE big_table ADD INDEX idx_col (col)");
?>

Authentication Plugins

MariaDB supports server-side authentication plugins that extend or replace the default MySQL authentication mechanisms. The most notable example is the parsec plugin, which became the default in recent MariaDB versions.

Currently, mysqlnd provides only limited support for MariaDB-specific authentication plugins. As a result, connections to MariaDB servers using these plugins can fail, or require fallback to less secure authentication methods, unless external mysqlnd authentication plugins are installed (for example, mysqlnd_parsec or mysqlnd_ed25519 from Packagist).

This feature is invisible to application code:

By supporting MariaDB authentication plugins at the protocol level, PHP extensions can safely and efficiently connect to current and future MariaDB servers without requiring separate extensions or application changes.

Extended Metadata

MariaDB extends standard MySQL metadata with additional type information to provide more precise data handling. This extended metadata allows clients to differentiate types that MySQL treats identically, improving type awareness, validation, and performance in PHP applications.

Key MariaDB extensions include:

* ext_type — indicates the server-side extended type for a column or parameter. * ext_format — indicates the data format used for transmission, which may differ from the standard MySQL format. This is particularly relevant for binary or structured types such as geometry or network types.

Type Format
GEOMETRY POINT, LINESTRING, POLYGON, ...
STRING JSON, UUID, INET, ...

Together, ext_type and ext_format allow clients to:

From a PHP perspective, exposing this extended metadata through mysqli allows applications to:

PDO Considerations (Out of Scope)

PDO_MySQL currently does not support array binding or bulk execution semantics required to expose MariaDB-specific bulk operations in a clean and consistent way.

This RFC focuses on enhancing mysqlnd and mysqli first. Future RFCs may extend PDO_MySQL once the underlying mysqlnd capabilities are available and an appropriate PDO API design is agreed upon.

Implementation / Proof-of-Concept

A proof-of-concept implementation is available at: php-src 8.6-mariadb POC

The implementation modifies:

mysqlnd

mysqli

The patch is intended for PHP 8.6 and requires MariaDB Server ≥ 10.2 for full functionality.

Fallback behavior for MySQL Server remains unchanged and continues to use repeated COM_STMT_EXECUTE.

Visibility and Impacts

MariaDB-specific features can be categorized based on whether they require changes to the PHP API or are handled entirely internally by mysqlnd or the PHP extensions.

Visible Features

These features require new methods, functions, or options in PHP to expose MariaDB-specific functionality to developers:

Feature PHP Extension Description Required API Change
Server capabilities mysqli Additional connection properties New: $link->server_capabiities and $link->ext_server_capabilities
Bulk Execution mysqli Execute multiple sets of parameters efficiently in one round-trip $stmt->executemany($rows)
Progress Indication mysqli Report progress of long-running operations Additional parameter MYSQLI_OPT_PROGRESS_CALLBACK for mysqli_options

Impact: Applications can call these new methods directly to leverage MariaDB-specific performance or monitoring features. Backward compatibility with MySQL is maintained because these methods can be no-ops when connected to a MySQL server.

Invisible Features

These features are internal optimizations that improve performance or protocol behavior without requiring changes to application code:

Feature PHP Extension Description Notes
Prepared Statement Metadata Caching mysqlnd Avoids resending metadata for repeated prepares Transparent to application code
Authentication Plugins mysqlnd Supports MariaDB authentication plugins (e.g., parsec) Applications use standard connection functions
Extended Metadata / Type Granularity mysqli Provides ext_type and ext_format for geometry, INET, UUID Transparent to application code

Impacts

Performance Improvements: Existing PHP functions that prepare and execute statements, such as mysql_execute_query() (introduced in PHP 8.2), could be updated to use execute_direct when connected to a MariaDB server. This would allow one-time statements to bypass the extra round-trip and metadata fetch, providing immediate performance gains.

Backward Compatibility: All invisible features are fully backward-compatible with MySQL. Visible features are MariaDB-specific but can be safely ignored or no-oped when connected to a MySQL server.

Backward Incompatible Changes

None

RFC Impact

Open Issues

Future Scope

Implementation

References

Rejected Features

Changelog

If there are major changes to the initial proposal, please include a short summary with a date or a link to the mailing list announcement here, as not everyone has access to the wikis' version history.