• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Using Perl Stored Procedures for MariaDB
 

Using Perl Stored Procedures for MariaDB

on

  • 1,710 views

https://www.percona.com/live/mysql-conference-2013/sessions/perl-stored-procedures-mariadb

https://www.percona.com/live/mysql-conference-2013/sessions/perl-stored-procedures-mariadb

Statistics

Views

Total Views
1,710
Views on SlideShare
1,123
Embed Views
587

Actions

Likes
3
Downloads
10
Comments
0

32 Embeds 587

http://antbits.blogspot.com 220
http://antbits.blogspot.de 55
http://antbits.blogspot.it 44
http://antbits.blogspot.cz 43
http://antbits.blogspot.fr 32
http://antbits.blogspot.ru 31
http://antbits.blogspot.in 26
http://antbits.blogspot.com.es 20
http://antbits.blogspot.co.uk 17
http://antbits.blogspot.kr 13
http://antbits.blogspot.ca 8
http://antbits.blogspot.hu 8
http://antbits.blogspot.com.br 8
http://antbits.blogspot.no 7
http://antbits.blogspot.nl 7
http://antbits.blogspot.be 6
http://antbits.blogspot.sg 5
http://antbits.blogspot.jp 5
http://antbits.blogspot.gr 4
http://antbits.blogspot.com.au 4
http://antbits.blogspot.com.ar 3
http://antbits.blogspot.tw 3
http://antbits.blogspot.ie 3
http://antbits.blogspot.pt 3
http://antbits.blogspot.fi 2
http://antbits.blogspot.se 2
https://www.google.com 2
http://antbits.blogspot.co.nz 2
http://antbits.blogspot.mx 1
http://antbits.blogspot.co.il 1
http://antbits.blogspot.ch 1
http://antbits.blogspot.co.at 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Using Perl Stored Procedures for MariaDB Using Perl Stored Procedures for MariaDB Presentation Transcript

    • Using Perl StoredProcedureswith MariaDBAntony T Curtis <atcurtis@gmail.com>Special thanks to LinkedIn for permitting personal projects
    • Why Perl?• CPAN• "Multiplicity" / Thread-friendly.• Lots of Perl code already written.• MySQL UDFs have no access control.• MySQL UDFs cannot execute dynamic SQL.• Faster than “native” Stored Procedures.
    • Perl Stored Procedures• Implemented as Perl modules.• Use DBD::mysql to access database.• Runs in-process with MariaDB.• Easier to debug than SQL stored routines.
    • Hello WorldMariaDB [Demo]> CREATE PROCEDURE PerlHello()-> DYNAMIC RESULT SETS 1-> NO SQL-> LANGUAGE Perl-> EXTERNAL NAME "HelloWorld::test";Query OK, 0 rows affected (0.02 sec)MariaDB [Demo]> call PerlHello();+-----------------------+| message |+-----------------------+| Hello World from Perl |+-----------------------+1 row in set (0.03 sec)Query OK, 0 rows affected (0.03 sec)package HelloWorld;# put this file in <prefix>/lib/mysql/perluse 5.008008;use strict;use warnings;use Symbol qw(delete_package);require Exporter;our @ISA = qw(Exporter);our @EXPORT_OK = qw( );our @EXPORT = qw( test );our $VERSION = 0.01;sub test(){return {message => Hello World from Perl,};}1;
    • Hello WorldMariaDB [Demo]> CREATE PROCEDURE PerlHello()-> DYNAMIC RESULT SETS 1-> NO SQL-> LANGUAGE Perl-> EXTERNAL NAME "HelloWorld::test";Query OK, 0 rows affected (0.02 sec)MariaDB [Demo]> call PerlHello();+-----------------------+| message |+-----------------------+| Hello World from Perl |+-----------------------+1 row in set (0.03 sec)Query OK, 0 rows affected (0.03 sec)package HelloWorld;# put this file in <prefix>/lib/mysql/perluse 5.008008;use strict;use warnings;use Symbol qw(delete_package);require Exporter;our @ISA = qw(Exporter);our @EXPORT_OK = qw( );our @EXPORT = qw( test );our $VERSION = 0.01;sub test(){return {message => Hello World from Perl,};}1;
    • Error handling or dieMariaDB [Demo]> CREATE PROCEDURE PerlError()-> DYNAMIC RESULT SETS 1-> NO SQL-> LANGUAGE Perl-> EXTERNAL NAME "GoodbyeWorld::test";Query OK, 0 rows affected (0.00 sec)MariaDB [Demo]> call PerlError();ERROR 1220 (HY000): Cannot open file: Nosuch file or directory at /usr/local/mysql/lib/plugin/perl/GoodbyeWorld.pm line 16.package GoodbyeWorld;# put this file in <prefix>/lib/mysql/perluse 5.008008;use strict;use warnings;use Symbol qw(delete_package);require Exporter;our @ISA = qw(Exporter);our @EXPORT_OK = qw( );our @EXPORT = qw( test );our $VERSION = 0.01;sub test({open FILE, "</something/nonexist"or die "Cannot open file: $!";return {message => Goodbye World from Perl,};}1;
    • Reading DataMariaDB [employees]> CREATE PROCEDURE employee(-> empno INT)-> DYNAMIC RESULT SETS 1-> READS SQL DATA-> LANGUAGE Perl-> EXTERNAL NAME "ReadData::test";Query OK, 0 rows affected (0.02 sec)MariaDB [employees]> call employee(10034)G*************************** 1. row***************************birth_date: 1962-12-29emp_no: 10034first_name: Badergender: Mhire_date: 1988-09-21last_name: Swan1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)package ReadData;# put this file in <prefix>/lib/mysql/perluse 5.008008;use strict;use warnings;use Symbol qw(delete_package);require Exporter;our @ISA = qw(Exporter);our @EXPORT_OK = qw( );our @EXPORT = qw( test );our $VERSION = 0.01;our $DSN = ‘dbi:mysql:employees’;use DBI;use DBD::mysql;sub test($){my($emp_no) = @_;my $dbh = DBI->connect($DSN, undef, undef) ||die "Failed in call to DBI->connect, $!";my $s = $dbh->prepare(“SELECT * FROM employees WHERE emp_no=?”);$s->execute(int $emp_no);return $s->fetchrow_hashref;}1;
    • Reading DataMariaDB [employees]> CREATE PROCEDURE employee(-> empno INT)-> DYNAMIC RESULT SETS 1-> READS SQL DATA-> LANGUAGE Perl-> EXTERNAL NAME "ReadData::test";Query OK, 0 rows affected (0.02 sec)MariaDB [employees]> call employee(10034)G*************************** 1. row***************************birth_date: 1962-12-29emp_no: 10034first_name: Badergender: Mhire_date: 1988-09-21last_name: Swan1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)package ReadData;# put this file in <prefix>/lib/mysql/perluse 5.008008;use strict;use warnings;use Symbol qw(delete_package);require Exporter;our @ISA = qw(Exporter);our @EXPORT_OK = qw( );our @EXPORT = qw( test );our $VERSION = 0.01;our $DSN = ‘dbi:mysql:employees’;use DBI;use DBD::mysql;sub test($){my($emp_no) = @_;my $dbh = DBI->connect($DSN, undef, undef) ||die "Failed in call to DBI->connect, $!";my $s = $dbh->prepare(“SELECT * FROM employees WHERE emp_no=?”);$s->execute(int $emp_no);return $s->fetchrow_hashref;}1;
    • Modifying DataMariaDB [employees]> CREATE PROCEDURE-> makesummary(-> empno INT)-> MODIFIES SQL DATA-> LANGUAGE Perl-> EXTERNAL NAME "ModifyData::test";Query OK, 0 rows affected (0.00 sec)MariaDB [employees]> call makesummary;sub test(){my $dbh = DBI->connect($DSN, undef, undef) ||die "Failed in call to DBI->connect, $!";$dbh->begin_work or die $!;my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)");my $emps = $dbh->selectall_arrayref("select emp_no, max(salary) salary from employees "."left join salaries using (emp_no) group by emp_no",{ Slice => {} });foreach my $emp (@$emps){$ins->execute($emp->{emp_no}, $emp->{salary}) or die $!;}$dbh->commit or die $!;return undef;}
    • Modifying DataMariaDB [employees]> CREATE PROCEDURE-> makesummary(-> empno INT)-> MODIFIES SQL DATA-> LANGUAGE Perl-> EXTERNAL NAME "ModifyData::test";Query OK, 0 rows affected (0.00 sec)MariaDB [employees]> call makesummary;Query OK, 0 rows affected (18.02 sec)sub test(){my $dbh = DBI->connect($DSN, undef, undef) ||die "Failed in call to DBI->connect, $!";$dbh->begin_work or die $!;my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)");my $emps = $dbh->selectall_arrayref("select emp_no, max(salary) salary from employees "."left join salaries using (emp_no) group by emp_no",{ Slice => {} });foreach my $emp (@$emps){$ins->execute($emp->{emp_no}, $emp->{salary}) or die $!;}$dbh->commit or die $!;return undef;}
    • Modifying DataMariaDB [employees]> CREATE PROCEDURE-> makesummary(-> empno INT)-> MODIFIES SQL DATA-> LANGUAGE Perl-> EXTERNAL NAME "ModifyData::test";Query OK, 0 rows affected (0.00 sec)MariaDB [employees]> call makesummary;Query OK, 0 rows affected (18.02 sec)MariaDB [employees]> select count(*)-> from summary;+----------+| count(*) |+----------+| 300024 |+----------+1 row in set (0.15 sec)sub test(){my $dbh = DBI->connect($DSN, undef, undef) ||die "Failed in call to DBI->connect, $!";$dbh->begin_work or die $!;my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)");my $emps = $dbh->selectall_arrayref("select emp_no, max(salary) salary from employees "."left join salaries using (emp_no) group by emp_no",{ Slice => {} });foreach my $emp (@$emps){$ins->execute($emp->{emp_no}, $emp->{salary}) or die $!;}$dbh->commit or die $!;return undef;}
    • Modifying DataMariaDB [employees]> CREATE PROCEDURE-> makesummary(-> empno INT)-> MODIFIES SQL DATA-> LANGUAGE Perl-> EXTERNAL NAME "ModifyData::test";Query OK, 0 rows affected (0.00 sec)MariaDB [employees]> call makesummary;Query OK, 0 rows affected (18.02 sec)MariaDB [employees]> select count(*)-> from summary;+----------+| count(*) |+----------+| 300024 |+----------+1 row in set (0.15 sec)sub test(){my $dbh = DBI->connect($DSN, undef, undef) ||die "Failed in call to DBI->connect, $!";$dbh->begin_work or die $!;my $ins = $dbh->prepare("INSERT INTO summary VALUES (?,?)");my $emps = $dbh->selectall_arrayref("select emp_no, max(salary) salary from employees "."left join salaries using (emp_no) group by emp_no",{ Slice => {} });foreach my $emp (@$emps){$ins->execute($emp->{emp_no}, $emp->{salary}) or die $!;}$dbh->commit or die $!;return undef;}select statement - 2 seconds300k inserts in 16 seconds== 18k inserts per second
    • More than just procs• CPAN is a large library...• Can extend MariaDB’s functionality.• How about using HTTP::Daemon?
    • Server Monitoringsub daemon(){my $d = HTTP::Daemon->new(LocalAddr => 127.0.0.1,LocalPort => 8080,) ||die "Failed in call to HTTP::Daemon->new, $!";my $dbh = DBI->connect("dbi:mysql:mysql", undef, undef) ||die "Failed in call to DBI->connect, $!";while (my $c = $d->accept){while (my $r = $c->get_request){if (exists $pages{$r->url->path}){$pages{$r->url->path}->($dbh, $c, $r);}else{$c->send_error(RC_NOT_FOUND);}}$c->close;undef $c;}}What if we can useHTTP::Daemon?
    • Server Monitoring/statusz => sub {my ($dbh,$c,$r) = @_;return $c->send_error(RC_FORBIDDEN)if $r->method ne GET;my $sth = $dbh->prepare_cached(q{SELECT VARIABLE_NAME name, VARIABLE_VALUE valueFROM INFORMATION_SCHEMA.GLOBAL_STATUS}, { Slice => {} });$sth->execute() || die $sth->errstr;my $response = HTTP::Response->new(200, undef,HTTP::Headers->new(Content_Type => "application/json",));my $result = {};while (my $row = $sth->fetchrow_arrayref){$result->{$row->[0]} = $row->[1];}$response->add_content(to_json($result,{ ascii => 1, pretty => 1 }));return $c->send_response($response);},Fetching currentserver status could beas simple as fetchinghttp://127.0.0.1/statusz
    • Status• Code hosted at LaunchPad.• Contributing to MariaDB 10.0 soon.• Stuff needs to be tidied up.• Future steps include better Table Functions.