[Solar-svn] Revision 3291
pmjones at solarphp.com
pmjones at solarphp.com
Thu Jul 31 16:03:59 CDT 2008
Solar_Sql_Adapter_MysqlReplicated: [BRK] Per conversation with Clay Loveless, make the default connection be the *slave*, and connect to the master only as needed. This is based on the idea that most connections are reads, not writes. Thanks, Clay.
Modified: trunk/Solar/Sql/Adapter/MysqlReplicated.php
===================================================================
--- trunk/Solar/Sql/Adapter/MysqlReplicated.php 2008-07-31 21:02:16 UTC (rev 3290)
+++ trunk/Solar/Sql/Adapter/MysqlReplicated.php 2008-07-31 21:03:59 UTC (rev 3291)
@@ -87,156 +87,180 @@
/**
*
- * A PDO-style DSN for the slave server.
+ * Which slave key the [[$_dsn]] property was built from.
*
- * The [[$_dsn]] property is for the master server.
+ * @var mixed
*
- * @var string
- *
*/
- protected $_dsn_slave;
+ protected $_dsn_key;
/**
*
- * Which slave key the [[$_dsn_slave]] property was built from.
+ * A PDO-style DSN for the master server.
*
- * @var mixed
+ * The [[$_dsn]] property is for the slave server.
*
+ * @var string
+ *
*/
- protected $_dsn_slave_key;
+ protected $_dsn_master;
/**
*
- * A PDO object for accessing the slave server.
+ * A PDO object for accessing the master server.
*
- * The [[$_pdo]] property is for the master server.
+ * The [[$_pdo]] property is for the slave server.
*
* @var PDO
*
* @see $_pdo
*
*/
- protected $_pdo_slave;
+ protected $_pdo_master;
/**
*
- * Get the slave PDO connection object (connects to the database if
+ * Sets the connection-specific cache key prefix.
+ *
+ * @param string $prefix The cache-key prefix. When null, defaults to
+ * the class name, a slash, and the md5() of the DSN **for the master**.
+ *
+ * @return string
+ *
+ */
+ public function setCacheKeyPrefix($prefix = null)
+ {
+ if ($prefix === null) {
+ $prefix = get_class($this) . '/' . md5($this->_dsn_master);
+ }
+
+ $this->_cache_key_prefix = $prefix;
+ }
+
+ /**
+ *
+ * Get the master PDO connection object (connects to the database if
* needed).
*
* @return PDO
*
*/
- public function getPdoSlave()
+ public function getPdoMaster()
{
- $this->connect();
- return $this->_pdo_slave;
+ $this->connectMaster();
+ return $this->_pdo_master;
}
/**
*
- * Sets the DSN for the slave to a random slave server.
+ * Sets the DSN for the slave and the master; the slave is picked at
+ * random from the list of slaves.
*
* For example, "mysql:host=127.0.0.1;dbname=test"
*
* @return void
*
- * @see $_dsn_slave
+ * @see $_dsn
*
- * @see $_dsn_slave_key
+ * @see $_dsn_key
*
+ * @see $_dsn_master
+ *
*/
- protected function _setDsnSlave()
+ protected function _setDsn()
{
- // the dsn info
- $dsn = array();
+ // convenient reference to all slaves
+ $slaves = $this->_config['slaves'];
- // pick a random slave from the list
- $key = array_rand($this->_config['slaves']);
+ // pick a random slave key
+ $this->_dsn_key = array_rand(array_keys($slaves));
- // convenience copy of the slave info
- $slave = $this->_config['slaves'][$key];
+ // set DSN for slave
+ $this->_dsn = $this->_buildDsn($slaves[$this->_dsn_key]);
- // socket, or host-and-port? (can't use both.)
- if (! empty($slave['sock'])) {
-
- // use a socket
- $dsn[] = 'unix_socket=' . $slave['sock'];
-
- } else {
-
- // use host and port
- if (! empty($slave['host'])) {
- $dsn[] = 'host=' . $slave['host'];
- }
-
- if (! empty($slave['port'])) {
- $dsn[] = 'port=' . $slave['port'];
- }
-
- }
-
- // database name
- if (! empty($slave['name'])) {
- $dsn[] = 'dbname=' . $slave['name'];
- }
-
- // done, set values
- $this->_dsn_slave_key = $key;
- $this->_dsn_slave = $this->_pdo_type . ':' . implode(';', $dsn);
+ // set DSN for master
+ $this->_dsn_master = $this->_buildDsn($this->_config);
}
/**
*
- * Connects to the master server and a random slave server.
+ * Connects to a random slave server.
*
* Does not re-connect if we already have active connections.
*
* @return void
*
*/
- protected function connect()
+ public function connect()
{
- // connect to master
- parent::connect();
-
- // connect to slave?
- if ($this->_pdo_slave) {
+ // already connected?
+ if ($this->_pdo) {
return;
}
- // set the slave dsn and key
- $this->_setDsnSlave();
-
// which slave dsn key was used?
// need this so we have the right credentials.
- $key = $this->_dsn_slave_key;
+ $key = $this->_dsn_key;
// start profile time
$time = microtime(true);
// attempt the connection
- $this->_pdo_slave = new PDO(
- $this->_dsn_slave,
+ $this->_pdo = new PDO(
+ $this->_dsn,
$this->_config['slaves'][$key]['user'],
$this->_config['slaves'][$key]['pass']
);
// post-connection tasks
- $this->_postConnectSlave();
+ $this->_postConnect();
// retain the profile data?
- $this->_addProfile($time, '__CONNECT_SLAVE');
+ $this->_addProfile($time, '__CONNECT');
}
/**
*
- * Force the slave connection to use the same attributes as the master.
+ * Connects to the master server.
*
+ * Does not re-connect if we already have an active connection.
+ *
* @return void
*
*/
- protected function _postConnectSlave()
+ public function connectMaster()
{
+ // already connected?
+ if ($this->_pdo_master) {
+ return;
+ }
+
+ // start profile time
+ $time = microtime(true);
+
+ // attempt the connection
+ $this->_pdo = new PDO(
+ $this->_dsn,
+ $this->_config['user'],
+ $this->_config['pass']
+ );
+
+ // post-connection tasks
+ $this->_postConnectMaster();
+
+ // retain the profile data?
+ $this->_addProfile($time, '__CONNECT_MASTER');
+ }
+
+ /**
+ *
+ * Force the master connection to use the same attributes as the slave.
+ *
+ * @return void
+ *
+ */
+ protected function _postConnectMaster()
+ {
// adapted from example at
// <http://us.php.net/manual/en/pdo.getattribute.php>
$attribs = array(
@@ -248,7 +272,7 @@
foreach ($attribs as $attr) {
$key = constant("PDO::ATTR_$attr");
$val = $this->_pdo->getAttribute($key);
- $this->_pdo_slave->setAttribute($key, $val);
+ $this->_pdo_master->setAttribute($key, $val);
}
}
@@ -262,7 +286,7 @@
public function disconnect()
{
parent::diconnect();
- $this->_pdo_slave = null;
+ $this->_pdo_master = null;
}
/**
@@ -286,18 +310,16 @@
// prepare the statment
try {
if ($is_select) {
- // all SELECTs go to the slave.
- // keep config info in case of exception
- $key = $this->_dsn_slave_key;
+ // slave
+ $this->connect();
+ $key = $this->_dsn_key;
$config = $this->_config['slaves'][$key];
- // prepare the statement
- $prep = $this->_pdo_slave->prepare($stmt);
+ $prep = $this->_pdo_master->prepare($stmt);
} else {
- // all other commands go to the master.
- // keep config info in case of exception
+ // master
+ $this->connectMaster();
$config = $this->_config;
- // prepare the statement
- $prep = $this->_pdo->prepare($stmt);
+ $prep = $this->_pdo_master->prepare($stmt);
}
} catch (PDOException $e) {
// note that we use $config as set in the try block above
@@ -319,4 +341,69 @@
return $prep;
}
+
+ /**
+ *
+ * Leave autocommit mode and begin a transaction **on the master**.
+ *
+ * @return void
+ *
+ */
+ public function begin()
+ {
+ $this->connectMaster();
+ $time = microtime(true);
+ $result = $this->_pdo_master->beginTransaction();
+ $this->_addProfile($time, '__BEGIN');
+ return $result;
+ }
+
+ /**
+ *
+ * Commit a transaction and return to autocommit mode **on the master**.
+ *
+ * @return void
+ *
+ */
+ public function commit()
+ {
+ $this->connectMaster();
+ $time = microtime(true);
+ $result = $this->_pdo_master->commit();
+ $this->_addProfile($time, '__COMMIT');
+ return $result;
+ }
+
+ /**
+ *
+ * Roll back a transaction and return to autocommit mode **on the master**.
+ *
+ * @return void
+ *
+ */
+ public function rollback()
+ {
+ $this->connectMaster();
+ $time = microtime(true);
+ $result = $this->_pdo_master->rollBack();
+ $this->_addProfile($time, '__ROLLBACK');
+ return $result;
+ }
+
+ /**
+ *
+ * Get the last auto-incremented insert ID from the database.
+ *
+ * @param string $table The table name on which the auto-increment occurred.
+ *
+ * @param string $col The name of the auto-increment column.
+ *
+ * @return int The last auto-increment ID value inserted to the database.
+ *
+ */
+ public function lastInsertId($table = null, $col = null)
+ {
+ $this->connectMaster();
+ return $this->_pdo_master->lastInsertId();
+ }
}
More information about the Solar-svn
mailing list