yii2.0主从数据库实现源码分析

来源:互联网 发布:知美整形是正规医院吗? 编辑:程序博客网 时间:2024/06/05 04:28
主从数据库,主库写,从库读,主库挂掉了,不影响任何读操作,从库挂掉了,读写都在主库操作。
The Connection component supports load balancing and failover between slaves. When performing a read query for the first time, theConnection component will randomly pick a slave and try connecting to it. If the slave is found "dead", it will try another one. If none of the slaves is available, it will connect to the master. By configuring a yii\db\Connection::serverStatusCache, a "dead" server can be remembered so that it will not be tried again during a yii\db\Connection::serverRetryInterval.

配置项
// common configuration for slaves            'slaveConfig' => [                'username' => 'root',                'password' => 'xxxx',                'charset' => 'utf8',                'attributes' => [                    \PDO::ATTR_TIMEOUT => 10,                ],            ],            'slaves' => [                ['dsn' => 'mysql:host=xxxx;dbname=yii2advanced'],                //['dsn' => 'mysql:host=xxxx;dbname=yii2advanced'],//其他从服务器

读操作的栈调用



源码在\yii\db\Connection.php中,调用栈顺序,从#3开始,先是调用getSlavePdo(),再调用getSlave(false),参数是在有从数据库的前提下,true表示返回主数据库,false表示返回从数据库,openFromPool($this->slaves, $this->slaveConfig)返回一个从数据库,在openFromPool中array_merge($slaves, $slaveConfig),然后遍历这个配置数组,直到能创建一个连接或者遍历完返回,在foreach里面会调用open进行数据库连接。


$this->pdo = $this->createPdoInstance();
$this->initConnection();
会初始化PDO,所以请求过来的时候,如果不进行数据库操作,则不初始化pdo,如果是读操作,会初始化一个pdo,从数据库的,如果是写操作,则会初始化两个pdo一个主的一个从的。写操作时候如下:


写操作的原理,代码部分:



打印出来的栈信息,从这个栈信息,可以看出来先是会初始化一个从的pdo,
在初始化主pdo的时候,
getMasterPdo()->open()
$this->masters不为空,所以会调用openFromPool()
openFromPool里面又会调用open(),不同的是这一次$this->masters为空了,所有就会走到try里面,这也就是22只打印了两次,另一次是初始化从的时候,open栈信息却有三次。




上面说到了在写操作的时候,也会初始化从库,可是写入却是在主库上做的,下面解释一下为什么要初始化从库:
看上面的写操作都调用了prepare操作,




看这里的输出,就知道了一次写操作会执行三次Sql语句,两次getSlavePdo(),一次getMasterPdo(),两次getSlavePdo(),会调用到一次open()方法,所以打印了一次open的栈信息,一次getMasterPdo()会调用两次open()方法,所以是两次栈信息。
同时从这里也可以看出来,一个写操作,读取表的列,约束条件等的操作都是在从库上;只有插入是在主库上。

1 0