You probably can easily find many articles on the internet show how to use DBD::mysql, they are all showing how to do with select, delete, update piece by piece. However, when you start to use them in programming, you will have to write a function frame and put them in. Here, I show you each piece in function, which I've been using them in my script for years. And, they've been tested in heavy duty cluster environment, thousands of concurret processes with millions of records in MySQL db. You can feel free to copy and use them in you program directly.

Before get started, here is the documentation about DBD::mysql
http://search.cpan.org/~capttofu/DBD-mysql-4.023/lib/DBD/mysql.pm

Function #1, dbinit, to read db configuration file, host, db, user, pass etc..

###############################################################################
# SUB:          dbInit
# PURPOSE:      initialize database setup
#
# ARGS:         string $msg  - message to log
#               string $type - type is _INFO, _WARN or _EXIT
#
# NOTES:
# RETURNS:      n/a
###############################################################################
sub dbInit
{
  if( !defined $g_top ) {
    logMsg( "top directory not set.", _DIE );
  }
  my $config = $g_top."/".DBCONF;
  ## Does not seem to work! .. hmmm.....
  ## do $config or logMsg( "cannot process DB params in $config: $!", _DIE );
  open( FILE, $config )  or logMsg( "cannot open $config: $!", _DIE );
  my @configs = <FILE>;
  close( FILE ) or logMsg( "cannot close $config: $!", _DIE );
  my $entry;
  my $var;
  my $value;
  foreach $entry (@configs) {
    chomp( $entry );
    $entry =~ s/^(\s)+//;
    $entry =~ s/(\s)+$//;
    if( length( $entry ) > 0 ) {
      if( ! ($entry =~ /^#/) ) { ## ignore comments.
        ($var, $value) = split( /\s*=\s*/, $entry, 2 );
        $value =~ s/'*//g;
        $g_dbparams{$var} = $value;
      }
    }
  }
}

Function #2 db connection

In my script, I declare dbh as a global variable, so that in the following script or child process, the same connection can be reused, same some overhead time.

###############################################################################
# SUB:          dbConninit
# PURPOSE:      get sharable db connection handle to mysql
#
# ARGS:
#
# NOTES:
# RETURNS:      $dbh - databse connector
###############################################################################
sub dbConninit
{
  my $cnt = 0;
  my $sleeptime = 10;
  my $connStr = 'DBI:mysql:'.$g_dbparams{"db"}.':'.$g_dbparams{"host"};
  $g_debug and logMsg( "Will make a new connection ", _LOG );
  do {
    if( $cnt > 0 ) {
      logMsg( "Problem connecting to mysql: sleeping.", _LOG );
      $sleeptime += $cnt*5;
      sleep $sleeptime ;
    }
    $cnt++;
    $g_dbh = DBI->connect( $connStr, $g_dbparams{"user"}, $g_dbparams{"pass"},
     {RaiseError => 0, PrintError => 0} );
  } while( ! $g_dbh and $cnt <= 10 );

  if( ! $g_dbh ) {
    dbErr( "Cannot connect to database.", "die" );
  }
  return($g_dbh);
}

Function #3, db connection reuse.

As I said in function #2, dbh is declared as global variable, so this function is to verify the connection is ok, if not, call dbconninit again for new connection.

###############################################################################
# SUB:          dbConnect
# PURPOSE:      connect to mysql server
#
# ARGS:
#
# NOTES:
# RETURNS:      $dbh - databse connector or dies if no connection
###############################################################################
sub dbConnect
{
  my $reconnect = 0;
  if( defined($g_dbh) ) {
    ## test the connection to see if it is good; if not then reconnect below
    my $sth = $g_dbh->prepare( "DESC volumes" );
    if( $sth->execute() ) {
      $sth->finish();
    }
    else {
      $reconnect = 1;
    }
  }
  else {
    $reconnect = 1;
  }
  if( $reconnect ) {
   $g_dbh= dbConninit();
  }
  return( $g_dbh );
}

Function #4 dbFinish

After everything is done, use this function to disconnect db

###############################################################################
# SUB:        dbFinish
# PURPOSE:    disconnect from mysql server
#
# ARGS:        n/a
#
# NOTES: # RETURNS:    n/a
###############################################################################
sub dbFinish
{
  $g_dbh->disconnect() or dbErr( "Cannot close mysql connection.", "warn" ) ;
  return();
}

Function #5, dbsingleselect

Do a SQL select, return you only single result.

###############################################################################
# SUB:          dbsingleselect
# PURPOSE:      Apply this sql select query diff from dbSingleSelect.
#               use for transaction without dbconnect
# ARGS:         string $q - query or operation to apply
#               int $kind - _NUMERIC or _STRING
#
# NOTES:        The type of SELECT submitted may only return a single result!
###############################################################################
sub dbsingleselect
{
  my $q = $_[0];
  my $dbh = $_[1];
  my $kind = $_[2];
  my ($res);
  my $sth = $dbh->prepare( $q );
  $sth->execute() or dbErr( "Unable to execute query ".qq($q), _DIE );
  $res = $sth->fetchrow_array();
  $sth->finish();
  if( ! defined $res ) {
    if( $kind == _STRING ) {
      $res = "";
    }
    elsif( $kind == _NUMERIC ) {
      $res = 0;
    }
    elsif( $kind == _ZERO ) { ## here we want to distinguish zero from NULL
      $res = -1;
    }
  }
  return( $res );
}

Function #5, dbMultiselect

For SQL query for multiple rows, return a array ref, Results stored like this

row $i, column 1 -- > $list[$i][0]
row $i, column 2 -- > $list[$i][1]

Here is the function

###############################################################################
# SUB:          dbMultiSelect
# PURPOSE:      Apply this sql select query.
#
# ARGS:         string $q - query to apply
#
# NOTES:        return a array ref!
# RETURNS:      result returned by this query
###############################################################################
sub dbMultiSelect
{
  my $q = $_[0];
  my $res;
  my @list = ();
  my $dbh = dbConnect();
  my $sth = $dbh->prepare( $q );
  $sth->execute() or dbErr( "Unable to execute query ".qq($q), _DIE );
  my $arrset = $sth->fetchall_arrayref or dbErr( "Unable to fetch", _DIE );
  $sth->finish();
  my( $i, $nrows );
  ## note that indexing and row counts! start at zero
  $nrows = $#{$arrset};
  if( $nrows < 0 ) {
    #$g_debug and logMsg( $q.":no matched row", _LOG );
  }
  foreach $i ( 0..$nrows ) {
    push(@list, $arrset->[$i]);
  }
  return( @list );
}

Function #7, dbh->do

You can use it for create, insert, delete and update for db change

###############################################################################
# SUB:          dbDoOp
# PURPOSE:      Apply this sql query.  It changes the database, and is there-
#                fore logged.
#
# ARGS:         string $q - query or operation to apply
#
# NOTES:
# RETURNS:      result (# of rows affected) returned by this query
###############################################################################
sub dbDoOp
{
  my $q = $_[0];
  my $logsql = $_[1];
  my $res;
  my $dbh = dbConnect();
  $res = $dbh->do( $q ) or dbErr( "Unable to do query ".qq($q), _DIE );
  #$dbh->disconnect( ) or dbErr( "Cannot close connection.", "warn" );
  if($logsql == _LOG) {
    logSQL( $q );
  }
  if( ! defined $res ) {
    logMsg( "Bad result from sql operation: ".qq($q), _LOG );
    $res = -1;
  }
  elsif( $res == 0E0 )
    $res = 1;
  }
  return( $res );
}

Function #8, multiple updates in a sequence with table lock.

Good for a transction kind update.

###############################################################################
# SUB:          dbDoMulOps
# PURPOSE:      Apply this sql query.  It changes the database, and is there-
#                fore logged.
#
# ARGS:         string @Ops - queries or operations to apply
#
# NOTES:
# RETURNS:      result (# of rows affected) returned by this query
###############################################################################
sub dbDoMulOps
{
  my @Ops = @{$_[0]};
  my @locktables = @{$_[1]};
  my $logsql = $_[2];
  my ($res,$locks,$dbh);
  my $q="lock tables  " ;
  foreach $locks (@locktables) {
    $q .= $locks ;
}
  $dbh = dbConnect();
  #$res = $dbh->do( $q ) or dbErr( "Unable to do query ".qq($q), _DIE );
  if($logsql == _NOLOG) {
    foreach $q (@Ops) {
      $res = $dbh->do( $q ) or dbErr( "Unable to do query ".qq($q), _DIE );
    }
  }
  else {  # log sql
    foreach $q (@Ops) {
      $res = $dbh->do( $q ) or dbErr( "Unable to do query ".qq($q), _DIE );
      logSQL( $q );
    }
  }
  $q="unlock tables";
  #$res = $dbh->do( $q ) or dbErr( "Unable to do query ".qq($q), _DIE );
  #$dbh->disconnect( ) or dbErr( "Cannot close connection.", "warn" );

  if( ! defined $res ) {
    logMsg( "Bad result from sql operation: ".qq($q), _LOG );
    $res = -1;
  }
  elsif( $res == 0E0 ) {## for SL 3 on amanda - some versions of perl-dbi/mysql
                        ## return 0e0 on update if no rows were affected.  for
                        ## our purposes this might as well be 1
    $res = 1;
  }
  return( $res );
}

Function #9, capture db error.

###############################################################################
# SUB:          dbErr
# PURPOSE:      report database errors
#
# ARGS:         string $msg  - message to log
#               string $type - type is _INFO, _WARN or _EXIT
#
# NOTES:
# RETURNS:      n/a
###############################################################################
sub dbErr
{
  my $msg = shift( @_ );
  my $type = shift( @_ );
  my $dbmsg = sprintf( "%s\nSQL Err: %s (%s)", $msg, $DBI::err, $DBI::errstr );
  if( $type ne _EXIT ) {
    logMsg( $dbmsg, _LOG );
  }
  else {
    logMsg( $dbmsg, _DIE );
  }
}

Function #10, log SQL

Used for SQL log, show you which SQL executed, and good for rollback.

###############################################################################
# SUB:          logSQL
# PURPOSE:      log SQL statements
#
# ARGS:         string $msg  - message to log
#
# NOTES:
# RETURNS:      n/a
###############################################################################
sub logSQL
{
  my $msg = $_[0];
  my $config = $g_top."/".SQLLOG;
  my $pid = getpid();
  my $time = strftime( "%b %d %H:%M:%S", localtime() );
  open(FILE, ">> $config") or logMsg( "Couldn't open $config for writing: $!",
   _DIE );
  $g_debug and print FILE "# $time\n";
  $g_debug and print FILE "# (PID $pid): \n";
  print FILE "$msg ;\n";
  close( FILE ) or logMsg( "cannot close $config: $!", _DIE );
}