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] == 1 && 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.