Ruslan Bondar Site: RuslanBondar/projects/scripts/mysqlphpconnector

PHP My SQL Connectror

Use it on you own risk

All master slave must have one user/password for connection

When you send array of servers to my_connect, at first position go master, then all slaves.

Example

include('My_DB.php');

  $SEND_ERROR_TO = 'admin@example.com';

  my_connect(array('db1','db2'),'USER','PASSWORD','DB');

      ...

  my_query('select ...');  // go to slave (db2)

      ...

  my_query('select ...'); // go to slave (db2)

      ...

  my_query('insert ...'); // go to master (db1)

      ...

Source :

<?php

/**

* MySql DataBase Package

*

* <p>Base DataBase Access Package. Allow access to many SQL servers in master/slave mode</p>

* <code>

*   include('My_DB.php');

*   $SEND_ERROR_TO = 'admin@example.com';

*   my_connect(array('db1','db2'),'USER','PASSWORD','DB');

*       ...

*   my_query('select ...');

*       ...

*   my_query('select ...');

*       ...

*       ...

* </code>

* @autor Ruslan Bondar

* @since 2005-08-28

* @version $Id: My_DB.php,v 1.7 2007/03/13 13:02:27 rus Exp $

* @package My_DB

  * @link http://rus.leaping.net/Ruslan_Bondar/projekty/scripts/mysqlphpconnector

*/

/**

* Connect to one or many sql servers.

* @param string/array $mysql_host one or meny sql server host names.

* @param string $DB_USER sql server user name.

* @param string $DB_PASSWORD sql server passwod.

* @param string $DB_DB sql server database name.

* @param string $DB_ENGINE sql server engine (default mysql).

* @access public

*/

function my_connect($mysql_host,$DB_USER,$DB_PASSWORD,$DB_DB,$DB_ENGINE='mysql'){

    global $SQL_CONNECTIONS,$SQL_DB;

    if (count($SQL_CONNECTIONS)>0) return $SQL_CONNECTIONS[0];

    $SQL_DB = new My_Db();

    if (!is_array($mysql_host)){

        return $SQL_DB->add_connection($mysql_host,$DB_USER,$DB_PASSWORD,$DB_DB,1);

    }else{

        $master array_shift($mysql_host);

        foreach($mysql_host as $k=>$v)

            $SQL_DB->add_connection($v,$DB_USER,$DB_PASSWORD,$DB_DB,0);

        return $SQL_DB->add_connection($master,$DB_USER,$DB_PASSWORD,$DB_DB,1);

    }

}

/**

**

* Error notify

* @param string $sql sql that get error

* @param resourse $RESOURCE connection that get error

*/

function debug_send_sql_error($sql,$RESOURCE){

        global $SEND_ERROR_TO,$SEND_DB_ERRORS,$SQL_DB;

        $err $SQL_DB->error($RESOURCE);

        $send 1;

        if ($SEND_DB_ERRORS[$err] == && preg_match('/^( |\()*select /i',$sql)) $send 0;

        if ($SEND_ERROR_TO && $send) {

                $subj "==".$_SERVER["SERVER_NAME"]."== PHP error in SQL query";

                $message .= "$sql:\n\n";

                $message .= $err."\n";

                $message .= print_r(debug_backtrace(),true);

                $message .= "SESSION:\n";

                $message .= print_r($_SESSION,true)."\n";

                $message .= "SERVER:\n";

                $message .= print_r($_SERVER,true)."\n";

                mail($SEND_ERROR_TO$subj$message);

                $SEND_DB_ERRORS[$err] = 1;

        }

}

/**

* Send sql query to one of sql servers.

* @param string $sql sql to execute.

* @param int $send_slave 1 - automatic 0 - never send this sql to slave 2 - always send this sql to slave (default 1)

* @param array $change_tables array of tables to cheak for master only request.

* @access public

*/

function my_query($sql,$send_slave=1,$change_tables=array(),$allow_recall=true){

        global $DEBUG$error$SQL_CONNECTIONS,$SQL_DB;

        $RESOURCE $SQL_CONNECTIONS[0];

        if ($SQL_CONNECTIONS){

            if ($send_slave && $SQL_DB->check_sql_for_good_for_master($sql)){

                if (($send_slave == 2) || ($send_slave && $SQL_DB->check_sql_for_table_update($sql)))

//                  $RESOURCE = $SQL_CONNECTIONS[rand(0,count($SQL_CONNECTIONS)-1)];

                    $RESOURCE = ($SQL_CONNECTIONS[1])?$SQL_CONNECTIONS[1]:$SQL_CONNECTIONS[0];

            } else {

                $SQL_DB->add_updated_table($sql,$change_tables);

            }

        }

        $return = (is_object($DEBUG))?$DEBUG->debug_query($sql,$RESOURCE):$SQL_DB->query($sql,$RESOURCE);

        if (!$return) {

            if ($SQL_DB->errno($RESOURCE) == 2013 && $allow_recall){

                $isHelpt 0;

                $isHelpt 0;

                if ($SQL_DB->ping($RESOURCE)){

                    my_query($sql,$send_slave,$change_tables,false);

                    $isHelpt 1;

                }

            }

            else

            {

                debug_send_sql_error($sql,$RESOURCE);

            }

        }

        return $return;

}

/**

* Get inserted row ID.

* @access public

*/

function my_insert_id(){

    global $SQL_DB;

    return $SQL_DB->insert_id();

}

/**

 * Abstract My DB class

 *

 * Default MY DB functions.

 * @package My_DB

*/

class My_DB {

/**

* Update array of tables updated this script

*/

function add_updated_table($sql,$change_tables=array()){

    if ($change_tables == 'none') return;

    $s str_replace("\n"," ",$sql);

    $s str_replace("\r"," ",$s);

    $s str_replace("\t"," ",$s);

    if (preg_match('/^ *alter .*table *([ _a-zA-Z0-9.]+) /i',$s,$matches))                      $this->add_updated_table_safe($matches[1]);

    if (preg_match('/^ *update.* ([ _a-zA-Z0-9.]+) +set/i',$s,$matches))                        $this->add_updated_table_safe($matches[1]);

    if (preg_match('/^ *insert *into *([ _a-zA-Z0-9.]+)( |\()/i',$s,$matches))                  $this->add_updated_table_safe($matches[1]);

    if (preg_match('/^ *replace *(into)? +([ _.a-zA-Z0-9]+) +( |\(|values|set|select)/i',$s,$matches))  $this->add_updated_table_safe($matches[1]);

    if (preg_match('/^ *delete .*from +([_a-zA-Z0-9.]+) +(where|using)/i',$s,$matches))         $this->add_updated_table_safe($matches[1]);

    if (preg_match('/^ *create.*table +([_a-zA-Z0-9.]+) +(as|select|\()/i',$s,$matches))        $this->add_updated_table_safe($matches[1]);

}

/**

* Extract table name from str

*/

function add_updated_table_safe($tablename){

    $s trim($tablename);

    if (strpos($s,'.'))

        list($db,$s) = explode('.',$s);

    if (!$s) return;

    $this->SQL_CONNECTIONS_TABLE_UPDATED[$s] = 1;

}

/**

* Check sql for running on slave

*/

function check_sql_for_good_for_master($sql){

    if (preg_match('/^( |\(|\n)*commit/i',$sql)) $this->alltomaster 1;

    if (preg_match('/^( |\(|\n)*set /i',$sql)) $this->alltomaster 1;

    if (!preg_match('/^( |\(|\n)*select (.|\n)*from/i',$sql)) return 0;

    if (preg_match('/LAST_INSERT_ID/i',$sql)) return 0;

    return 1;

}

/**

* Check sql for using updated tables

*/

function check_sql_for_table_update($sql){

    if ($this->alltomaster) return 0;

    if (!is_array($this->SQL_CONNECTIONS_TABLE_UPDATED)) return 1;

    foreach ($this->SQL_CONNECTIONS_TABLE_UPDATED as $table=>$v )

        if (strpos($sql,$table))

            return 0;

    return 1;

}

/**

* Execute sql

*/

function query($q,$res){

    return mysql_query($q,$res);

}

/**

* Return affected rows

*/

function affected_rows($res){

    return mysql_affected_rows($res);

}

/**

* Return errror

*/

function errno($res){

    return mysql_errno($res);

}

/**

* Return errno

*/

function error($res){

    return mysql_error($res);

}

/**

* Return ping

*/

function ping($res){

    return mysql_ping($res);

}

/**

* Return insert_id

*/

function insert_id(){

    global $SQL_CONNECTIONS;

    return mysql_insert_id($SQL_CONNECTIONS[0]);

}

/**

* Add connection

*/

function add_connection($mysql_host,$DB_USER,$DB_PASSWORD,$DB_DB,$ismaster=0){

    global $SQL_CONNECTIONS;

//    print "$mysql_host,$DB_USER,$DB_PASSWORD<br>";

    $conn=mysql_pconnect($mysql_host,$DB_USER,$DB_PASSWORD);

    if (mysql_error()) { if ($ismaster) die(mysql_error()); return;}

    $ret mysql_select_db($DB_DB);

    if (mysql_error()) { if ($ismaster) die(mysql_error()); return;}

    $id count($SQL_CONNECTIONS);

    if ($ismaster)      $id 0;

    elseif($id<2)       $id++;

    $SQL_CONNECTIONS[$id] = $conn;

    return $conn;

}

}

?>

Released under the BSD license.