ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro-Mysql/Mysql.pm
(Generate patch)

Comparing Coro-Mysql/Mysql.pm (file contents):
Revision 1.3 by root, Mon Jun 1 12:03:21 2009 UTC vs.
Revision 1.4 by root, Sat Jul 18 05:58:27 2009 UTC

26F<libmysqlclient> library as DBD::mysql, otherwise it will not work. 26F<libmysqlclient> library as DBD::mysql, otherwise it will not work.
27 27
28Also, while this module makes database handles non-blocking, you still 28Also, while this module makes database handles non-blocking, you still
29cannot run multiple requests in parallel on the same database handle. If 29cannot run multiple requests in parallel on the same database handle. If
30you want to run multiple queries in parallel, you have to create multiple 30you want to run multiple queries in parallel, you have to create multiple
31database connections, one for each thread that runs queries. 31database connections, one for each thread that runs queries. Not doing so
32can corrupt your data - use a Coro::Semaphore when in doubt.
32 33
33If you make sure that you never run two or more requests in parallel, you 34If you make sure that you never run two or more requests in parallel, you
34cna freely share the database handles between threads, of course. 35can freely share the database handles between threads, of course.
35 36
36Also, this module uses a number of "unclean" techniques (patching an 37Also, this module uses a number of "unclean" techniques (patching an
37internal libmysql structure for one thing) and was hacked within a few 38internal libmysql structure for one thing) and was hacked within a few
38hours on a long flight to Malaysia. 39hours on a long flight to Malaysia.
39 40
40It does, however, check whether it indeed got the structure layout 41It does, however, check whether it indeed got the structure layout
41correct, so you should expect perl exceptions or early crashes as opposed 42correct, so you should expect perl exceptions or early crashes as opposed
42to data corruption when something goes wrong. 43to data corruption when something goes wrong during patching.
43 44
44=head2 SPEED 45=head2 SPEED
45 46
46This module is implemented in XS, and as long as mysqld replies quickly 47This module is implemented in XS, and as long as mysqld replies quickly
47enough, it adds no overhead to the standard libmysql communication 48enough, it adds no overhead to the standard libmysql communication
48routines (which are very badly written). 49routines (which are very badly written, btw.).
49 50
50For very fast queries ("select 0"), this module can add noticable overhead 51For very fast queries ("select 0"), this module can add noticable overhead
51(around 15%) as it tries to switch to other coroutines when mysqld doesn't 52(around 15%) as it tries to switch to other coroutines when mysqld doesn't
52deliver the data instantly. 53deliver the data instantly.
53 54
54For most types of queries, there will be no overhead, especially on 55For most types of queries, there will be no overhead, especially on
55multicore systems where your perl process can do other things while mysqld 56multicore systems where your perl process can do other things while mysqld
56does its stuff. 57does its stuff.
58
59=head2 LIMITATIONS
60
61This module only supports "standard" mysql connection handles - this
62means unix domain or TCP sockets, and excludes SSL/TLS connections, named
63pipes (windows) and shared memory (also windows). No support for these
64connection types is planned, either.
65
66=head1 FUNCTIONS
67
68Coro::Mysql offers a single user-accessible function:
57 69
58=over 4 70=over 4
59 71
60=cut 72=cut
61 73
75 87
76sub readable { &Coro::Handle::FH::readable } 88sub readable { &Coro::Handle::FH::readable }
77sub writable { &Coro::Handle::FH::writable } 89sub writable { &Coro::Handle::FH::writable }
78 90
79BEGIN { 91BEGIN {
80 our $VERSION = '0.2'; 92 our $VERSION = '1.0';
81 93
82 require XSLoader; 94 require XSLoader;
83 XSLoader::load Coro::Mysql::, $VERSION; 95 XSLoader::load Coro::Mysql::, $VERSION;
84} 96}
85 97
89so it becomes compatible to Coro threads. 101so it becomes compatible to Coro threads.
90 102
91After that, it returns the patched handle - you should always use the 103After that, it returns the patched handle - you should always use the
92newly returned database handle. 104newly returned database handle.
93 105
94It is safe to call this function on any database handle, but it will only 106It is safe to call this function on any database handle (or just about any
95do anything to L<DBD::mysql> handles, others are returned unchanged. 107value), but it will only do anything to L<DBD::mysql> handles, others are
108returned unchanged. That means it is harmless when applied to database
109handles of other databases.
96 110
97=cut 111=cut
98 112
99sub unblock { 113sub unblock {
100 my ($DBH) = @_; 114 my ($DBH) = @_;
105 open my $fh, "+>&" . $DBH->{sockfd} 119 open my $fh, "+>&" . $DBH->{sockfd}
106 or croak "Coro::Mysql unable to clone mysql fd"; 120 or croak "Coro::Mysql unable to clone mysql fd";
107 121
108 $fh = Coro::Handle::unblock $fh; 122 $fh = Coro::Handle::unblock $fh;
109 123
110 _patch $sock, $DBH->{sockfd}, tied ${$fh}; 124 _patch $sock, $DBH->{sockfd}, $fh, tied ${$fh};
111 $DBH->{private_Coro_Mysql} = guard {
112 _unpatch $sock;
113 undef $fh;
114 };
115 } 125 }
116 126
117 $DBH 127 $DBH
118} 128}
119 129
1201; 1301;
121 131
122=back 132=back
123 133
134=head1 USAGE EXAMPLE
135
136This example uses L<PApp::SQL> and L<Coro::on_enter> to implement a
137function C<with_db>, that connects to a database, uses C<unblock> on the
138resulting handle and then makes sure that C<$PApp::SQL::DBH> is set to the
139(per-thread) database handle when the given thread is running (it does not
140restore any previous value of $PApp::SQL::DBH, however):
141
142 use Coro;
143 use Coro::Mysql;
144 use PApp::SQL;
145
146 sub with_db($$$&) {
147 my ($database, $user, $pass, $cb) = @_;
148
149 my $dbh = Coro::Mysql::unblock DBI->connect ($database, $user, $pass)
150 or die $DBI::errstr;
151
152 Coro::on_enter { $PApp::SQL::DBH = $dbh };
153
154 $cb->();
155 }
156
157This function makes it possible to easily use L<PApp::SQL> with
158L<Coro::Mysql>, without worrying about database handles.
159
160 # now start 10 threads doing stuff
161 async {
162
163 with_db "DBI:mysql:test", "", "", sub {
164 sql_exec "update table set col = 5 where id = 7";
165
166 my $st = sql_exec \my ($id, $name),
167 "select id, name from table where name like ?",
168 "a%";
169
170 while ($st->fetch) {
171 ...
172 }
173
174 my $id = sql_insertid sql_exec "insert into table values (1,2,3)";
175 # etc.
176 };
177
178 } for 1..10;
179
180=head1 SEE ALSO
181
182L<Coro>, L<PApp::SQL> (a user friendly but efficient wrapper around DBI).
183
124=head1 AUTHOR 184=head1 AUTHOR
125 185
126 Marc Lehmann <schmorp@schmorp.de> 186 Marc Lehmann <schmorp@schmorp.de>
127 http://home.schmorp.de/ 187 http://home.schmorp.de/
128 188

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines