--- Coro-Mysql/Mysql.pm 2009/06/01 12:03:21 1.3 +++ Coro-Mysql/Mysql.pm 2009/07/18 05:58:27 1.4 @@ -28,10 +28,11 @@ Also, while this module makes database handles non-blocking, you still cannot run multiple requests in parallel on the same database handle. If you want to run multiple queries in parallel, you have to create multiple -database connections, one for each thread that runs queries. +database connections, one for each thread that runs queries. Not doing so +can corrupt your data - use a Coro::Semaphore when in doubt. If you make sure that you never run two or more requests in parallel, you -cna freely share the database handles between threads, of course. +can freely share the database handles between threads, of course. Also, this module uses a number of "unclean" techniques (patching an internal libmysql structure for one thing) and was hacked within a few @@ -39,13 +40,13 @@ It does, however, check whether it indeed got the structure layout correct, so you should expect perl exceptions or early crashes as opposed -to data corruption when something goes wrong. +to data corruption when something goes wrong during patching. =head2 SPEED This module is implemented in XS, and as long as mysqld replies quickly enough, it adds no overhead to the standard libmysql communication -routines (which are very badly written). +routines (which are very badly written, btw.). For very fast queries ("select 0"), this module can add noticable overhead (around 15%) as it tries to switch to other coroutines when mysqld doesn't @@ -55,6 +56,17 @@ multicore systems where your perl process can do other things while mysqld does its stuff. +=head2 LIMITATIONS + +This module only supports "standard" mysql connection handles - this +means unix domain or TCP sockets, and excludes SSL/TLS connections, named +pipes (windows) and shared memory (also windows). No support for these +connection types is planned, either. + +=head1 FUNCTIONS + +Coro::Mysql offers a single user-accessible function: + =over 4 =cut @@ -77,7 +89,7 @@ sub writable { &Coro::Handle::FH::writable } BEGIN { - our $VERSION = '0.2'; + our $VERSION = '1.0'; require XSLoader; XSLoader::load Coro::Mysql::, $VERSION; @@ -91,8 +103,10 @@ After that, it returns the patched handle - you should always use the newly returned database handle. -It is safe to call this function on any database handle, but it will only -do anything to L handles, others are returned unchanged. +It is safe to call this function on any database handle (or just about any +value), but it will only do anything to L handles, others are +returned unchanged. That means it is harmless when applied to database +handles of other databases. =cut @@ -107,11 +121,7 @@ $fh = Coro::Handle::unblock $fh; - _patch $sock, $DBH->{sockfd}, tied ${$fh}; - $DBH->{private_Coro_Mysql} = guard { - _unpatch $sock; - undef $fh; - }; + _patch $sock, $DBH->{sockfd}, $fh, tied ${$fh}; } $DBH @@ -121,6 +131,56 @@ =back +=head1 USAGE EXAMPLE + +This example uses L and L to implement a +function C, that connects to a database, uses C on the +resulting handle and then makes sure that C<$PApp::SQL::DBH> is set to the +(per-thread) database handle when the given thread is running (it does not +restore any previous value of $PApp::SQL::DBH, however): + + use Coro; + use Coro::Mysql; + use PApp::SQL; + + sub with_db($$$&) { + my ($database, $user, $pass, $cb) = @_; + + my $dbh = Coro::Mysql::unblock DBI->connect ($database, $user, $pass) + or die $DBI::errstr; + + Coro::on_enter { $PApp::SQL::DBH = $dbh }; + + $cb->(); + } + +This function makes it possible to easily use L with +L, without worrying about database handles. + + # now start 10 threads doing stuff + async { + + with_db "DBI:mysql:test", "", "", sub { + sql_exec "update table set col = 5 where id = 7"; + + my $st = sql_exec \my ($id, $name), + "select id, name from table where name like ?", + "a%"; + + while ($st->fetch) { + ... + } + + my $id = sql_insertid sql_exec "insert into table values (1,2,3)"; + # etc. + }; + + } for 1..10; + +=head1 SEE ALSO + +L, L (a user friendly but efficient wrapper around DBI). + =head1 AUTHOR Marc Lehmann