Ruslan Bondar Site: RuslanBondar/projects/scripts/mysqlphpconnector ...

Ruslan Bondar | Page Index | Recently Commented | Users | Registration | Вход:  Пароль:  

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.

Комментариев нет. [Показать комментарии/форму]