PHP is moving into a new era. With the introduction of Fibers in PHP 8.1, we can finally build long-running and high-performance applications that handle thousands of concurrent tasks. However, to truly unlock this power, we need database drivers that are built specifically for an asynchronous world.
Most existing PHP drivers are blocking. When you send a query, the entire process stands still while waiting for the database. This is a massive bottleneck for modern apps.
I built the Hibla MySQL Client to solve this. It is a ground-up implementation of the MySQL Binary Protocol designed specifically for the Hibla ecosystem.
Efficient connection management
In a traditional script, you connect and disconnect for every single request. In an async application, that is simply too slow. Hibla features a built-in Pool Manager that keeps connections warm and ready to use.
It includes "Check-on-Borrow" logic. This ensures that every connection you get is healthy and active. It also handles connection resetting. This means session variables or temporary tables from a previous task never leak into the next one.
use Hibla\Mysql\MysqlClient;
$db = new MysqlClient(
config: 'mysql://root:secret@127.0.0.1/app_db',
minConnections: 5,
maxConnections: 20
);
// You can easily monitor your pool health
print_r($db->stats);
/*
Output includes: active_connections, pooled_connections,
waiting_requests, and more.
*/
Handling transaction failures automatically
Transactions are often the most fragile part of database logic. Deadlocks and lock wait timeouts are common in busy systems. Usually, you have to write manual loops and complex retry logic to handle these transient errors.
Hibla builds this directly into the API. You can define a transaction block and tell the client how many times it should try again if an error occurs. It simplifies your code and makes your application much more resilient.
use Hibla\Sql\TransactionOptions;
await($db->transaction(function($tx) {
// This entire block will be retried automatically on deadlocks
$balance = await($tx->fetchValue("SELECT balance FROM accounts WHERE id = :id", null, ['id' => 1]));
await($tx->execute(
"UPDATE accounts SET balance = :b WHERE id = :id",
['b' => $balance - 100, 'id' => 1]
));
}, TransactionOptions::default()->withAttempts(3)));
Processing large datasets without memory spikes
When you need to process a million rows, loading them all into memory is not an option. Hibla supports true unbuffered streaming. This allows you to work through massive result sets one row at a time.
We also implemented a smart backpressure handler. If your code is processing rows slower than the database can send them, Hibla automatically pauses the underlying socket. It only resumes when your code is ready for more. This keeps your memory usage low and predictable even during heavy data exports.
$stream = await($db->stream("SELECT * FROM massive_log_table"));
// The stream pauses the socket automatically if the buffer fills up
foreach ($stream as $row) {
// Process each row one by one
await(doComplexProcessing($row));
}
echo "Stream finished. Total rows: " . $stream->stats->rowCount;
Stopping slow queries in their tracks
In a standard PHP environment, once you send a query, you are committed. If the user cancels their request or a timeout hits, the database keeps running that query anyway. This wastes server resources and holds up important locks.
Hibla solves this with side-channel cancellation. When you cancel a promise in PHP, the client opens a brief secondary connection to the server and issues a KILL QUERY command. The server stops the work immediately.
use Hibla\EventLoop\Loop;
$promise = $db->query("SELECT some_very_slow_calculation()");
// If we decide we do not want this anymore after 1 second...
Loop::addTimer(1.0, fn() => $promise->cancel());
try {
await($promise);
} catch (CancelledException $e) {
// The query was killed on the MySQL server instantly
echo "Query stopped and server resources were freed.";
}
Built for modern security and speed
This client is not a wrapper around older extensions. It talks directly to the MySQL socket. This allows us to support a wide range of modern features out of the box without any external dependencies.
This includes SSL and TLS encryption for secure data transfer. We also support zlib compression to save bandwidth on large queries. The driver handles both Native and SHA256 authentication plugins automatically.
// Simple configuration via URI for complex features
$db = new MysqlClient(
config: 'mysql://user@host/db?ssl=true&compress=true&charset=utf8mb4'
);
Moving PHP forward
The goal of this project is to make PHP feel as modern and capable as any other async-first language. By implementing the protocol from scratch, we get absolute control over the connection lifecycle.
You can find the project and the full documentation here:
https://github.com/hiblaphp/mysql
I would love to hear your feedback. Are you building long-running PHP applications? How are you handling database concurrency today?
Top comments (0)