Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
43333d9c
Commit
43333d9c
authored
Jul 11, 2014
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented master balancing.
parent
91e0c5ae
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
145 additions
and
88 deletions
+145
-88
Schema.php
extensions/sphinx/Schema.php
+1
-1
Command.php
framework/db/Command.php
+2
-2
Connection.php
framework/db/Connection.php
+136
-79
Schema.php
framework/db/Schema.php
+1
-1
Schema.php
framework/db/cubrid/Schema.php
+3
-3
QueryBuilder.php
framework/db/mssql/QueryBuilder.php
+1
-1
QueryBuilder.php
framework/db/pgsql/QueryBuilder.php
+1
-1
No files found.
extensions/sphinx/Schema.php
View file @
43333d9c
...
...
@@ -324,7 +324,7 @@ class Schema extends Object
public
function
quoteValue
(
$str
)
{
if
(
is_string
(
$str
))
{
return
$this
->
db
->
get
Read
Pdo
()
->
quote
(
$str
);
return
$this
->
db
->
get
Slave
Pdo
()
->
quote
(
$str
);
}
else
{
return
$str
;
}
...
...
framework/db/Command.php
View file @
43333d9c
...
...
@@ -161,9 +161,9 @@ class Command extends \yii\base\Component
$sql
=
$this
->
getSql
();
if
(
$forRead
||
$forRead
===
null
&&
$this
->
db
->
getSchema
()
->
isReadQuery
(
$sql
))
{
$pdo
=
$this
->
db
->
get
Read
Pdo
();
$pdo
=
$this
->
db
->
get
Slave
Pdo
();
}
else
{
$pdo
=
$this
->
db
->
get
Write
Pdo
();
$pdo
=
$this
->
db
->
get
Master
Pdo
();
}
try
{
...
...
framework/db/Connection.php
View file @
43333d9c
...
...
@@ -71,9 +71,9 @@ use yii\caching\Cache;
* $transaction->rollBack();
* }
* ~~~
*
*
* You also can use shortcut for the above like the following:
*
*
* ~~~
* $connection->transaction(function() {
* $order = new Order($customer);
...
...
@@ -81,15 +81,15 @@ use yii\caching\Cache;
* $order->addItems($items);
* });
* ~~~
*
*
* If needed you can pass transaction isolation level as a second parameter:
*
*
* ~~~
* $connection->transaction(function(Connection $db) {
* //return $db->...
* }, Transaction::READ_UNCOMMITTED);
* ~~~
*
*
* Connection is often used as an application component and configured in the application
* configuration like the following:
*
...
...
@@ -261,16 +261,16 @@ class Connection extends Component
* [[Schema]] class to support DBMS that is not supported by Yii.
*/
public
$schemaMap
=
[
'pgsql'
=>
'yii\db\pgsql\Schema'
,
// PostgreSQL
'mysqli'
=>
'yii\db\mysql\Schema'
,
// MySQL
'mysql'
=>
'yii\db\mysql\Schema'
,
// MySQL
'sqlite'
=>
'yii\db\sqlite\Schema'
,
// sqlite 3
'pgsql'
=>
'yii\db\pgsql\Schema'
,
// PostgreSQL
'mysqli'
=>
'yii\db\mysql\Schema'
,
// MySQL
'mysql'
=>
'yii\db\mysql\Schema'
,
// MySQL
'sqlite'
=>
'yii\db\sqlite\Schema'
,
// sqlite 3
'sqlite2'
=>
'yii\db\sqlite\Schema'
,
// sqlite 2
'sqlsrv'
=>
'yii\db\mssql\Schema'
,
// newer MSSQL driver on MS Windows hosts
'oci'
=>
'yii\db\oci\Schema'
,
// Oracle driver
'mssql'
=>
'yii\db\mssql\Schema'
,
// older MSSQL driver on MS Windows hosts
'dblib'
=>
'yii\db\mssql\Schema'
,
// dblib drivers on GNU/Linux (and maybe other OSes) hosts
'cubrid'
=>
'yii\db\cubrid\Schema'
,
// CUBRID
'sqlsrv'
=>
'yii\db\mssql\Schema'
,
// newer MSSQL driver on MS Windows hosts
'oci'
=>
'yii\db\oci\Schema'
,
// Oracle driver
'mssql'
=>
'yii\db\mssql\Schema'
,
// older MSSQL driver on MS Windows hosts
'dblib'
=>
'yii\db\mssql\Schema'
,
// dblib drivers on GNU/Linux (and maybe other OSes) hosts
'cubrid'
=>
'yii\db\cubrid\Schema'
,
// CUBRID
];
/**
* @var string Custom PDO wrapper class. If not set, it will use "PDO" or "yii\db\mssql\PDO" when MSSQL is used.
...
...
@@ -282,30 +282,70 @@ class Connection extends Component
*/
public
$enableSavepoint
=
true
;
/**
* @var Cache|string the cache object or the ID of the cache application component that is used to store
* the health status of the DB servers specified in [[masters]] and [[slaves]].
* This is used only when read/write splitting is enabled or [[masters]] is not empty.
*/
public
$serverStatusCache
=
'cache'
;
/**
* @var integer the retry interval in seconds for dead servers listed in [[masters]] and [[slaves]].
* This is used together with [[serverStatusCache]].
*/
public
$serverRetryInterval
=
600
;
/**
* @var boolean whether to enable read/write splitting by using [[slaves]] to read data.
* Note that if [[slaves]] is empty, read/write splitting will NOT be enabled no matter what value this property takes.
*/
public
$enableSlave
=
true
;
/**
* @var array list of slave connection configurations. When [[enableSlave]] is true, one of these slave
* configurations will be used to create a DB connection to perform read queries.
* @var array list of slave connection configurations. Each configuration is used to create a slave DB connection.
* When [[enableSlave]] is true, one of these configurations will be chosen and used to create a DB connection
* for performing read queries only.
* @see enableSlave
* @see slaveConfig
*/
public
$slaves
=
[];
/**
* @var integer the timeout in seconds for determining whether a slave is dead or not
* @see enableSlave
* @var array the configuration that should be merged with every slave configuration listed in [[slaves]].
* For example,
*
* ```php
* [
* 'username' => 'slave',
* 'password' => 'slave',
* 'attributes' => [
* // use a smaller connection timeout
* PDO::ATTR_TIMEOUT => 10,
* ],
* ]
* ```
*/
public
$slave
Timeout
=
10
;
public
$slave
Config
=
[]
;
/**
* @var Cache|string the cache object or the ID of the cache application component that is used to store
* the health status of the slaves.
* @see enableSlave
* @var array list of master connection configurations. Each configuration is used to create a master DB connection.
* When [[open()]] is called, one of these configurations will be chosen and used to create a DB connection
* which will be used by this object.
* Note that when this property is not empty, the connection setting (e.g. "dsn", "username") of this object will
* be ignored.
* @see masterConfig
*/
public
$
slaveCache
=
'cache'
;
public
$
masters
=
[]
;
/**
* @var integer the retry interval in seconds for dead slaves.
* @var array the configuration that should be merged with every master configuration listed in [[masters]].
* For example,
*
* ```php
* [
* 'username' => 'master',
* 'password' => 'master',
* 'attributes' => [
* // use a smaller connection timeout
* PDO::ATTR_TIMEOUT => 10,
* ],
* ]
* ```
*/
public
$
slaveRetryInterval
=
600
;
public
$
masterConfig
=
[]
;
/**
* @var Transaction the currently active transaction
...
...
@@ -320,7 +360,7 @@ class Connection extends Component
*/
private
$_driverName
;
/**
* @var Connection the currently active slave
* @var Connection the currently active slave
connection
*/
private
$_slave
=
false
;
...
...
@@ -367,22 +407,34 @@ class Connection extends Component
*/
public
function
open
()
{
if
(
$this
->
pdo
===
null
)
{
if
(
empty
(
$this
->
dsn
))
{
throw
new
InvalidConfigException
(
'Connection::dsn cannot be empty.'
);
}
$token
=
'Opening DB connection: '
.
$this
->
dsn
;
try
{
Yii
::
trace
(
$token
,
__METHOD__
);
Yii
::
beginProfile
(
$token
,
__METHOD__
);
$this
->
pdo
=
$this
->
createPdoInstance
();
$this
->
initConnection
();
Yii
::
endProfile
(
$token
,
__METHOD__
);
}
catch
(
\PDOException
$e
)
{
Yii
::
endProfile
(
$token
,
__METHOD__
);
throw
new
Exception
(
$e
->
getMessage
(),
$e
->
errorInfo
,
(
int
)
$e
->
getCode
(),
$e
);
if
(
$this
->
pdo
!==
null
)
{
return
;
}
if
(
!
empty
(
$this
->
masters
))
{
$db
=
$this
->
openFromPool
(
$this
->
masters
,
$this
->
masterConfig
);
if
(
$db
!==
null
)
{
$this
->
pdo
=
$db
->
pdo
;
return
;
}
else
{
throw
new
InvalidConfigException
(
'None of the master DB servers is available.'
);
}
}
if
(
empty
(
$this
->
dsn
))
{
throw
new
InvalidConfigException
(
'Connection::dsn cannot be empty.'
);
}
$token
=
'Opening DB connection: '
.
$this
->
dsn
;
try
{
Yii
::
trace
(
$token
,
__METHOD__
);
Yii
::
beginProfile
(
$token
,
__METHOD__
);
$this
->
pdo
=
$this
->
createPdoInstance
();
$this
->
initConnection
();
Yii
::
endProfile
(
$token
,
__METHOD__
);
}
catch
(
\PDOException
$e
)
{
Yii
::
endProfile
(
$token
,
__METHOD__
);
throw
new
Exception
(
$e
->
getMessage
(),
$e
->
errorInfo
,
(
int
)
$e
->
getCode
(),
$e
);
}
}
/**
...
...
@@ -643,7 +695,7 @@ class Connection extends Component
if
((
$pos
=
strpos
(
$this
->
dsn
,
':'
))
!==
false
)
{
$this
->
_driverName
=
strtolower
(
substr
(
$this
->
dsn
,
0
,
$pos
));
}
else
{
$this
->
_driverName
=
strtolower
(
$this
->
get
Read
Pdo
()
->
getAttribute
(
PDO
::
ATTR_DRIVER_NAME
));
$this
->
_driverName
=
strtolower
(
$this
->
get
Slave
Pdo
()
->
getAttribute
(
PDO
::
ATTR_DRIVER_NAME
));
}
}
return
$this
->
_driverName
;
...
...
@@ -662,12 +714,17 @@ class Connection extends Component
* Returns the PDO instance for read queries.
* When [[enableSlave]] is true, one of the slaves will be used for read queries, and its PDO instance
* will be returned by this method. If no slave is available, the [[writePdo]] will be returned.
* @return PDO the PDO instance for read queries.
* @param boolean $fallbackToMaster whether to return a master PDO in case none of the slave connections is available.
* @return PDO the PDO instance for read queries. Null is returned if no server is available.
*/
public
function
get
ReadPdo
(
)
public
function
get
SlavePdo
(
$fallbackToMaster
=
true
)
{
$db
=
$this
->
getSlave
();
return
$db
?
$db
->
pdo
:
$this
->
getWritePdo
();
$db
=
$this
->
getSlave
(
false
);
if
(
$db
===
null
)
{
return
$fallbackToMaster
?
$this
->
getMasterPdo
()
:
null
;
}
else
{
return
$db
->
pdo
;
}
}
/**
...
...
@@ -675,35 +732,36 @@ class Connection extends Component
* This method will open the master DB connection and then return [[pdo]].
* @return PDO the PDO instance for write queries.
*/
public
function
get
Write
Pdo
()
public
function
get
Master
Pdo
()
{
$this
->
open
();
return
$this
->
pdo
;
}
/**
* Returns the currently active slave.
* Returns the currently active slave
connection
.
* If this method is called the first time, it will try to open a slave connection when [[enableSlave]] is true.
* @param boolean $fallbackToMaster whether to return a master connection in case none of the slave connections is available.
* @return Connection the currently active slave. Null is returned if there is slave available.
*/
public
function
getSlave
()
public
function
getSlave
(
$fallbackToMaster
=
true
)
{
if
(
!
$this
->
enableSlave
)
{
return
null
;
return
$fallbackToMaster
?
$this
:
null
;
}
if
(
$this
->
_slave
!==
false
)
{
return
$this
->
_slave
;
}
else
{
return
$this
->
_slave
=
$this
->
openSlave
(
$this
->
slaves
);
if
(
$this
->
_slave
===
false
)
{
$this
->
_slave
=
$this
->
openFromPool
(
$this
->
slaves
,
$this
->
slaveConfig
);
}
return
$this
->
_slave
===
null
&&
$fallbackToMaster
?
$this
:
$this
->
_slave
;
}
/**
* Executes the provided callback by using the master connection.
*
* This method is provided so that you can temporarily force using the master connection to perform
* DB operations. For example,
* DB operations
even if they are read queries
. For example,
*
* ```php
* $result = $db->useMaster(function ($db) {
...
...
@@ -712,7 +770,7 @@ class Connection extends Component
* ```
*
* @param callable $callback a PHP callable to be executed by this method. Its signature is
* `function ($db)`. Its return value will be returned by this method.
* `function (
Connection
$db)`. Its return value will be returned by this method.
* @return mixed the return value of the callback
*/
public
function
useMaster
(
callable
$callback
)
...
...
@@ -725,49 +783,48 @@ class Connection extends Component
}
/**
* Selects a slave and opens the connection.
* @param array $slaves the list of candidate slave configurations
* @return Connection the opened slave connection, or null if no slave is available
* @throws InvalidConfigException if a slave configuration does not have "dsn" setting
* Opens the connection to a server in the pool.
* @param array $pool the list of connection configurations in the server pool
* @param array $sharedConfig the configuration common to those given in `$pool`.
* @return Connection the opened DB connection, or null if no server is available
* @throws InvalidConfigException if a configuration does not specify "dsn"
*/
protected
function
open
Slave
(
$slaves
)
protected
function
open
FromPool
(
array
$pool
,
array
$sharedConfig
)
{
if
(
empty
(
$
slaves
))
{
if
(
empty
(
$
pool
))
{
return
null
;
}
shuffle
(
$slaves
);
if
(
!
isset
(
$sharedConfig
[
'class'
]))
{
$sharedConfig
[
'class'
]
=
get_class
(
$this
);
}
$cache
=
is_string
(
$this
->
s
laveCache
)
?
Yii
::
$app
->
get
(
$this
->
slaveCache
,
false
)
:
$this
->
slave
Cache
;
$cache
=
is_string
(
$this
->
s
erverStatusCache
)
?
Yii
::
$app
->
get
(
$this
->
serverStatusCache
,
false
)
:
$this
->
serverStatus
Cache
;
foreach
(
$slaves
as
$config
)
{
shuffle
(
$pool
);
foreach
(
$pool
as
$config
)
{
$config
=
array_merge
(
$sharedConfig
,
$config
);
if
(
empty
(
$config
[
'dsn'
]))
{
throw
new
InvalidConfigException
(
'
One of the slave connections has an empty "dsn"
.'
);
throw
new
InvalidConfigException
(
'
The "dsn" option must be specified
.'
);
}
$key
=
[
__METHOD__
,
$config
[
'dsn'
]];
if
(
$cache
instanceof
Cache
&&
$cache
->
get
(
$key
))
{
// should not try this dead s
lave
now
// should not try this dead s
erver
now
continue
;
}
if
(
!
isset
(
$config
[
'class'
]))
{
$config
[
'class'
]
=
get_class
(
$this
);
}
/* @var $slave Connection */
$slave
=
Yii
::
createObject
(
$config
);
if
(
!
isset
(
$slave
->
attributes
[
PDO
::
ATTR_TIMEOUT
]))
{
$slave
->
attributes
[
PDO
::
ATTR_TIMEOUT
]
=
$this
->
slaveTimeout
;
}
/* @var $db Connection */
$db
=
Yii
::
createObject
(
$config
);
try
{
$
slave
->
open
();
return
$
slave
;
$
db
->
open
();
return
$
db
;
}
catch
(
\Exception
$e
)
{
Yii
::
warning
(
"
Slave (
{
$config
[
'dsn'
]
}
) not available
: "
.
$e
->
getMessage
(),
__METHOD__
);
Yii
::
warning
(
"
Connection (
{
$config
[
'dsn'
]
}
) failed
: "
.
$e
->
getMessage
(),
__METHOD__
);
if
(
$cache
instanceof
Cache
)
{
$cache
->
set
(
$key
,
1
,
$this
->
s
lave
RetryInterval
);
$cache
->
set
(
$key
,
1
,
$this
->
s
erver
RetryInterval
);
}
}
}
...
...
framework/db/Schema.php
View file @
43333d9c
...
...
@@ -369,7 +369,7 @@ abstract class Schema extends Object
return
$str
;
}
if
((
$value
=
$this
->
db
->
get
Read
Pdo
()
->
quote
(
$str
))
!==
false
)
{
if
((
$value
=
$this
->
db
->
get
Slave
Pdo
()
->
quote
(
$str
))
!==
false
)
{
return
$value
;
}
else
{
// the driver doesn't support quote (e.g. oci)
...
...
framework/db/cubrid/Schema.php
View file @
43333d9c
...
...
@@ -116,7 +116,7 @@ class Schema extends \yii\db\Schema
return
$str
;
}
$pdo
=
$this
->
db
->
get
Read
Pdo
();
$pdo
=
$this
->
db
->
get
Slave
Pdo
();
// workaround for broken PDO::quote() implementation in CUBRID 9.1.0 http://jira.cubrid.org/browse/APIS-658
$version
=
$pdo
->
getAttribute
(
\PDO
::
ATTR_CLIENT_VERSION
);
...
...
@@ -143,7 +143,7 @@ class Schema extends \yii\db\Schema
*/
protected
function
loadTableSchema
(
$name
)
{
$pdo
=
$this
->
db
->
get
Read
Pdo
();
$pdo
=
$this
->
db
->
get
Slave
Pdo
();
$tableInfo
=
$pdo
->
cubrid_schema
(
\PDO
::
CUBRID_SCH_TABLE
,
$name
);
...
...
@@ -266,7 +266,7 @@ class Schema extends \yii\db\Schema
*/
protected
function
findTableNames
(
$schema
=
''
)
{
$pdo
=
$this
->
db
->
get
Read
Pdo
();
$pdo
=
$this
->
db
->
get
Slave
Pdo
();
$tables
=
$pdo
->
cubrid_schema
(
\PDO
::
CUBRID_SCH_TABLE
);
$tableNames
=
[];
foreach
(
$tables
as
$table
)
{
...
...
framework/db/mssql/QueryBuilder.php
View file @
43333d9c
...
...
@@ -239,7 +239,7 @@ class QueryBuilder extends \yii\db\QueryBuilder
*/
protected
function
isOldMssql
()
{
$pdo
=
$this
->
db
->
get
Read
Pdo
();
$pdo
=
$this
->
db
->
get
Slave
Pdo
();
$version
=
preg_split
(
"/\./"
,
$pdo
->
getAttribute
(
\PDO
::
ATTR_SERVER_VERSION
));
return
$version
[
0
]
<
11
;
}
...
...
framework/db/pgsql/QueryBuilder.php
View file @
43333d9c
...
...
@@ -137,7 +137,7 @@ class QueryBuilder extends \yii\db\QueryBuilder
}
// enable to have ability to alter several tables
$this
->
db
->
get
Write
Pdo
()
->
setAttribute
(
\PDO
::
ATTR_EMULATE_PREPARES
,
true
);
$this
->
db
->
get
Master
Pdo
()
->
setAttribute
(
\PDO
::
ATTR_EMULATE_PREPARES
,
true
);
return
$command
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment