EV::MariaDB
Async MariaDB/MySQL client for Perl using libmariadb and the EV event loop.
Features
- Fully asynchronous connect, query, prepared statements
- Query pipelining via
mysql_send_query/mysql_read_query_result(up to 64 in-flight) - Prepared statements with automatic buffer sizing via max_length detection
- Row streaming via
query_streamfor large result sets - Transactions:
commit,rollback,autocommit - Connection utilities: ping, reset, change_user, select_db, reset_connection, set_charset
- Graceful async close via
close_async - Manual parameter binding with
bind_paramsandsend_long_datafor BLOBs - Column metadata (field names) returned as optional third callback argument
- Multi-result set support
Synopsis
use EV;
use EV::MariaDB;
my $m = EV::MariaDB->new(
host => 'localhost',
user => 'root',
password => '',
database => 'test',
on_connect => sub { print "connected\n" },
on_error => sub { warn "error: $_[0]\n" },
);
# simple query
$m->query("select * from users", sub {
my ($rows, $err, $fields) = @_;
if ($err) { warn $err; return }
for my $row (@$rows) {
print join(", ", @$row), "\n";
}
});
# prepared statement
$m->prepare("select * from users where id = ?", sub {
my ($stmt, $err) = @_;
die $err if $err;
$m->execute($stmt, [42], sub {
my ($rows, $err, $fields) = @_;
# ...
$m->close_stmt($stmt, sub { });
});
});
# pipelined queries (all sent before reading results)
for my $id (1..100) {
$m->q("select * from t where id = $id", sub {
my ($rows, $err) = @_;
# callbacks fire in order
});
}
EV::run;
Install
Requires EV and Alien::MariaDB (which finds or builds libmariadb).
cpanm EV Alien::MariaDB
perl Makefile.PL && make && make test
Set connection info for tests:
TEST_MARIADB_HOST=127.0.0.1 TEST_MARIADB_USER=root make test
# or via unix socket:
TEST_MARIADB_SOCKET=/var/run/mysqld/mysqld.sock make test
Benchmark
500,000 queries against MariaDB 11.8 with ENGINE=MEMORY tables (no disk I/O), localhost unix socket. Compared to DBD::MariaDB 1.24 (synchronous DBI driver).
SELECT (select 1+1)
| Method | q/s | us/q | vs DBD sync | |---|--:|--:|--:| | EV::MariaDB pipeline(64) | 121,033 | 8.3 | 2.4x | | EV::MariaDB prepared | 58,911 | 17.0 | 1.2x | | EV::MariaDB sequential | 50,468 | 19.8 | 1.0x | | DBD::MariaDB sync prepared | 52,828 | 18.9 | 1.1x | | DBD::MariaDB sync | 49,857 | 20.1 | 1.0x | | DBD::MariaDB async+EV | 49,437 | 20.2 | 1.0x |
INSERT
| Method | q/s | us/q | vs DBD sync | |---|--:|--:|--:| | EV::MariaDB pipeline(64) | 78,781 | 12.7 | 1.8x | | EV::MariaDB prepared | 55,214 | 18.1 | 1.2x | | DBD::MariaDB sync prepared | 55,996 | 17.9 | 1.3x | | EV::MariaDB sequential | 44,380 | 22.5 | 1.0x | | DBD::MariaDB sync | 44,684 | 22.4 | 1.0x | | DBD::MariaDB async+EV | 42,145 | 23.7 | 0.9x |
SELECT point lookup (hash-indexed MEMORY table)
| Method | q/s | us/q | vs DBD sync | |---|--:|--:|--:| | EV::MariaDB pipeline(64) | 50,004 | 20.0 | 1.6x | | EV::MariaDB prepared | 37,911 | 26.4 | 1.2x | | DBD::MariaDB sync prepared | 36,813 | 27.2 | 1.2x | | EV::MariaDB sequential | 30,640 | 32.6 | 1.0x | | DBD::MariaDB sync | 30,778 | 32.5 | 1.0x | | DBD::MariaDB async+EV | 30,005 | 33.3 | 1.0x |
Pipeline mode provides 1.6-2.4x throughput over sequential execution by batching up to 64 queries before reading results, eliminating round-trip latency.
API
See perldoc EV::MariaDB for full documentation, including:
query($sql, $cb)/q— execute SQL (callback receives$rows,$err,$fields)query_stream($sql, $cb)— stream rows one at a time for large result setsprepare($sql, $cb)/prep— prepare statementexecute($stmt, \@params, $cb)— execute prepared statementbind_params($stmt, \@params)— manually bind parameters (synchronous)send_long_data($stmt, $idx, $data, $cb)— send BLOB/CLOB data in chunksclose_stmt($stmt, $cb)— close prepared statementclose_async($cb)— graceful async connection closestmt_reset($stmt, $cb)— reset prepared statement statecommit($cb),rollback($cb),autocommit($mode, $cb)— transactionsping($cb),select_db($db, $cb),change_user(...)— utilitiesset_charset($charset, $cb)— change connection character setreset_connection($cb)— reset session state without reconnectingreset/reconnect— disconnect and reconnectfinish/disconnect— close connectionskip_pending— cancel all pending operationsescape($str)— escape string for SQLon_connect($cb),on_error($cb)— get/set handlerslib_version,lib_info— class methods for client library info
License
Same terms as Perl itself.