/ Built-in Clients

Built-in Clients

Parallel queries need a non-blocking database client. PDO has none, and the PHP extensions that do (mysqli, pgsql) are often disabled on shared hosting, and there is no such extension at all for SQL Server. So MikoORM includes its own clients for the MySQL, PostgreSQL and SQL Server (TDS) wire protocols, written in plain PHP. With them, async queries run in parallel without installing anything.


Which client is used

Databaseauto (default)extensionphp
MySQL / MariaDBmysqli if loaded, otherwise built-inmysqli only (one by one without it)built-in
PostgreSQLpgsql if loaded, otherwise built-inpgsql onlybuilt-in
SQL Serverbuilt-in TDS clientone by one on the main connectionbuilt-in

Choose per driver with the mysql_driver, pgsql_driver and sqlsrv_driver settings (DB_ASYNC_MYSQL_DRIVER ... in .env, or Async::configure([...])). The normal (sync) queries always use PDO.

The clients need only PHP's stream sockets, plus openssl for encrypted connections and mbstring for SQL Server.


Same results as PDO

The clients convert values the way the PDO drivers do, so a query returns identical rows whether it ran sync or async:

MySQL / MariaDBPostgreSQLSQL Server
Integersint (ZEROFILL columns stay strings, unsigned BIGINT above PHP_INT_MAX stays a string)int / bigint as intint as int; bigint as string
Decimalsstringstringstring (ODBC format, e.g. .50)
Floatsfloatfloatfloat
Booleansint (BIT(1) as int)boolint
Binarystringbytea decoded to bytesstring
DatesY-m-d H:i:s texttextODBC text (Y-m-d H:i:s.mmm)

Errors carry the same driver code and SQLSTATE (isDuplicateEntry(), isForeignKeyError() ... work the same). Speed is on par with the extensions: in local measurements 50,000 PostgreSQL rows took 115 ms with the built-in client and 117 ms with pgsql.


MySQL / MariaDB

FeatureSupport
Authenticationmysql_native_password, caching_sha2_password (MySQL 8 default, fast and full authentication; RSA key exchange without SSL), sha256_password, mysql_clear_password (TLS or Unix socket only), auth switch
EncryptionTLS from the usual PDO options: PDO::MYSQL_ATTR_SSL_CA, SSL_CERT, SSL_KEY, SSL_CAPATH, SSL_CIPHER, SSL_VERIFY_SERVER_CERT
Connectionhost / port or unix_socket, connect_timeout
Sessionthe same INIT_COMMAND as PDO (SET NAMES, timeouts, lc_time_names)
Charsetsutf8mb4, utf8 / utf8mb3, latin1, ascii (others use mysqli or run one by one)
Valuesinlined as escaped literals for the connection charset; NO_BACKSLASH_ESCAPES honoured
CancelKILL QUERY through the main connection
Stored proceduresCALL works; extra result sets are read and dropped
$connection = ConnectionFactory::make([
    'driver' => 'mysql', 'host' => 'db.example.com', 'database' => 'app',
    'username' => 'app', 'password' => 'secret',
    'options' => [PDO::MYSQL_ATTR_SSL_CA => '/etc/ssl/certs/db-ca.pem'],   // PDO and async connections
]);

MariaDB users that only allow auth_gssapi_client / unix_socket plugin logins need mysqli.


PostgreSQL

FeatureSupport
Authenticationscram-sha-256 (the server signature is checked), md5, password
Encryptionsslmode: prefer (default, like libpq; PGSSLMODE is read too), require, verify-ca, verify-full, allow, disable; sslrootcert, sslcert, sslkey
ConnectionTCP, or a Unix socket when host starts with / ('host' => '/var/run/postgresql')
Valuesreal bound parameters (extended query protocol)
CancelPostgreSQL cancel request on a second connection
$connection = ConnectionFactory::make([
    'driver' => 'pgsql', 'host' => 'db.example.com', 'database' => 'app',
    'username' => 'app', 'password' => 'secret',
    'sslmode' => 'verify-full', 'sslrootcert' => '/etc/ssl/certs/db-ca.pem',
]);

The SSL keys are also added to the PDO DSN, so sync and async connections use the same settings.


SQL Server

FeatureSupport
ProtocolTDS 7.4 (SQL Server 2012 and newer, Azure SQL)
AuthenticationSQL Server logins (username / password); not Windows / Kerberos authentication
Encryptionlike the ODBC driver: encrypt => true encrypts everything, without it only the login is encrypted; trust_server_certificate => true for self-signed certificates
Server addresshost + port, host,port, host\instance (SQL Browser lookup), Azure gateway redirects
Valuesreal parameters via sp_executesql
Textnvarchar as UTF-8; varchar / text converted from the column's code page (Turkish_CI_AS = CP1254 ...)
CancelTDS attention
Not read by the clientsql_variant and CLR types (geography, geometry, hierarchyid): such results are read again on the main connection, so the query still works
$connection = ConnectionFactory::make([
    'driver' => 'sqlsrv', 'host' => 'sql.example.com', 'port' => 1433, 'database' => 'app',
    'username' => 'app', 'password' => 'secret',
    'encrypt' => true, 'trust_server_certificate' => false,
]);

The sync queries still need pdo_sqlsrv and an ODBC driver; only the async queries use the built-in client.


SQLite

SQLite is a file, not a server: there is nothing to run queries in parallel on. Async methods there run one by one on the main connection and return the same results, so code written with ...Async() works on every database.


Troubleshooting

SymptomCause / fix
DB::supportsParallelQueries() is falseSQLite; enabled = false; SQL Server without username or without mbstring; MySQL charset not supported and no mysqli
Queries correct but not faster, Log/connection.log shows "Async connection failed"the extra connection could not be opened (connection limit, firewall, login plugin); queries ran on the main connection
AsyncTimeoutException (SQLSTATE HYT00)the timeout setting cancelled the query
TLS errors with sslmode=verify-full / encryptcheck the CA file (sslrootcert, PDO::MYSQL_ATTR_SSL_CA) or use trust_server_certificate for test servers

Force one client to compare: Async::configure(['pgsql_driver' => 'php']) or 'extension'.