search
HomeBackend DevelopmentPHP TutorialYii method to implement master-slave reading and writing separation in multiple databases_php tutorial

This article mainly introduces the method of Yii to realize the separation of master-slave reading and writing in multiple databases. It is a very practical skill to realize the separation function of master-slave reading and writing in multiple databases by extending the Yii database class. Friends who need it can refer to it. Next

The example in this article describes how Yii implements master-slave read and write separation in multiple databases. Share it with everyone for your reference. The specific analysis is as follows:

Yii framework database multi-database, master-slave, read-write separation implementation, functional description:

1. Realize master-slave database read-write separation master library: write slave library (can Multiple): Read

2. When the master database cannot be connected, you can set whether the slave database is writable

3. When all slave databases cannot be connected, you can set whether the master database is readable

4. If the connection from the database fails, you can set it to not connect again within N seconds

Use the yii extension to implement, the code is as follows:

The code is as follows:

<?php
/** 
 * 主数据库 写 从数据库(可多个)读 
 * 实现主从数据库 读写分离 主服务器无法连接 从服务器可切换写功能 
 * 从务器无法连接 主服务器可切换读功 
 * by lmt 
 * */ 
class DbConnectionMan extends CDbConnection { 
    public $timeout = 10; //连接超时时间 
    public $markDeadSeconds = 600; //如果从数据库连接失败 600秒内不再连接  
    //用 cache 作为缓存全局标记 
    public $cacheID = &#39;cache&#39;; 
 
    /** 
     * @var array $slaves.Slave database connection(Read) config array. 
     * 配置符合 CDbConnection. 
     * @example 
     * &#39;components&#39;=>array( 
     *   &#39;db&#39;=>array( 
     *    &#39;connectionString&#39;=>&#39;mysql://<master>&#39;, 
     *    &#39;slaves&#39;=>array( 
     *     array(&#39;connectionString&#39;=>&#39;mysql://<slave01>&#39;), 
     *     array(&#39;connectionString&#39;=>&#39;mysql://<slave02>&#39;), 
     *    ) 
     *   ) 
     * ) 
     * */ 
    public $slaves = array(); 
    /** 
     *  
     * 从数据库状态 false 则只用主数据库 
     * @var bool $enableSlave 
     * */ 
    public $enableSlave = true; 
 
    /** 
     * @var slavesWrite 紧急情况主数据库无法连接 切换从服务器(读写). 
     */ 
    public $slavesWrite = false; 
 
    /** 
     * @var masterRead 紧急情况从主数据库无法连接 切换从住服务器(读写). 
     */ 
    public $masterRead = false; 
 
    /** 
     * @var _slave 
     */ 
    private $_slave; 
 
    /** 
     * @var _disableWrite 从服务器(只读). 
     */ 
    private $_disableWrite = true; 
 
    /** 
     * 
     * 重写 createCommand 方法,1.开启从库 2.存在从库 3.当前不处于一个事务中 4.从库读数据 
     * @param string $sql 
     * @return CDbCommand 
     * */ 
    public function createCommand($sql = null) { 
        if ($this->enableSlave && !emptyempty($this->slaves) && is_string($sql) && !$this->getCurrentTransaction() && self::isReadOperation($sql) && ($slave = $this->getSlave()) 
        ) { 
            return $slave->createCommand($sql); 
        } else { 
            if (!$this->masterRead) { 
                if ($this->_disableWrite && !self::isReadOperation($sql)) { 
 
                    throw new CDbException("Master db server is not available now!Disallow write operation on slave server!"); 
                } 
            } 
            return parent::createCommand($sql); 
        } 
    } 
 
    /** 
     * 获得从服务器连接资源 
     * @return CDbConnection 
     * */ 
    public function getSlave() { 
        if (!isset($this->_slave)) { 
            shuffle($this->slaves); 
            foreach ($this->slaves as $slaveConfig) { 
                if ($this->_isDeadServer($slaveConfig[&#39;connectionString&#39;])) { 
                    continue; 
                } 
                if (!isset($slaveConfig[&#39;class&#39;])) 
                    $slaveConfig[&#39;class&#39;] = &#39;CDbConnection&#39;; 
 
                $slaveConfig[&#39;autoConnect&#39;] = false; 
                try { 
                    if ($slave = Yii::createComponent($slaveConfig)) { 
                        Yii::app()->setComponent(&#39;dbslave&#39;, $slave); 
                        $slave->setAttribute(PDO::ATTR_TIMEOUT, $this->timeout); 
                        $slave->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); 
                        $slave->setActive(true); 
                        $this->_slave = $slave; 
                        break; 
                    } 
                } catch (Exception $e) { 
                    $this->_markDeadServer($slaveConfig[&#39;connectionString&#39;]); 
                    Yii::log("Slave database connection failed!ntConnection string:{$slaveConfig[&#39;connectionString&#39;]}", &#39;warning&#39;); 
 
                    continue; 
                } 
            } 
 
            if (!isset($this->_slave)) { 
                $this->_slave = null; 
                $this->enableSlave = false; 
            } 
        } 
        return $this->_slave; 
    } 
 
    public function setActive($value) { 
        if ($value != $this->getActive()) { 
            if ($value) { 
                try { 
                    if ($this->_isDeadServer($this->connectionString)) { 
                        throw new CDbException(&#39;Master db server is already dead!&#39;); 
                    } 
                    //PDO::ATTR_TIMEOUT must set before pdo instance create 
                    $this->setAttribute(PDO::ATTR_TIMEOUT, $this->timeout); 
                    $this->open(); 
                } catch (Exception $e) { 
                    $this->_markDeadServer($this->connectionString); 
                    $slave = $this->getSlave(); 
                    Yii::log($e->getMessage(), CLogger::LEVEL_ERROR, &#39;exception.CDbException&#39;); 
                    if ($slave) { 
                        $this->connectionString = $slave->connectionString; 
                        $this->username = $slave->username; 
                        $this->password = $slave->password; 
                        if ($this->slavesWrite) { 
                            $this->_disableWrite = false; 
                        } 
                        $this->open(); 
                    } else { //Slave also unavailable 
                        if ($this->masterRead) { 
                            $this->connectionString = $this->connectionString; 
                            $this->username = $this->username; 
                            $this->password = $this->password; 
                            $this->open(); 
                        } else { 
                            throw new CDbException(Yii::t(&#39;yii&#39;, &#39;CDbConnection failed to open the DB connection.&#39;), (int) $e->getCode(), $e->errorInfo); 
                        } 
                    } 
                } 
            } else { 
                $this->close(); 
            } 
        } 
    } 
 
    /** 
     * 检测读操作 sql 语句 
     *  
     * 关键字: SELECT,DECRIBE,SHOW ... 
     * 写操作:UPDATE,INSERT,DELETE ... 
     * */ 
    public static function isReadOperation($sql) { 
        $sql = substr(ltrim($sql), 0, 10); 
        $sql = str_ireplace(array(&#39;SELECT&#39;, &#39;SHOW&#39;, &#39;DESCRIBE&#39;, &#39;PRAGMA&#39;), &#39;^O^&#39;, $sql); //^O^,magic smile 
        return strpos($sql, &#39;^O^&#39;) === 0; 
    } 
 
    /** 
     * 检测从服务器是否被标记 失败. 
     */ 
    private function _isDeadServer($c) { 
        $cache = Yii::app()->{$this->cacheID}; 
        if ($cache && $cache->get(&#39;DeadServer::&#39; . $c) == 1) { 
            return true; 
        } 
        return false; 
    } 
 
    /** 
     * 标记失败的slaves. 
     */ 
    private function _markDeadServer($c) { 
        $cache = Yii::app()->{$this->cacheID}; 
        if ($cache) { 
            $cache->set(&#39;DeadServer::&#39; . $c, 1, $this->markDeadSeconds); 
        } 
    } 
}


main.php configuration: components array, the code is as follows:

The code is as follows:

&#39;db&#39;=>array( 
        &#39;class&#39;=>&#39;application.extensions.DbConnectionMan&#39;,//扩展路径 
        &#39;connectionString&#39; => &#39;mysql:host=192.168.1.128;dbname=db_xcpt&#39;,//主数据库 写 
        &#39;emulatePrepare&#39; => true, 
        &#39;username&#39; => &#39;root&#39;, 
        &#39;password&#39; => &#39;root&#39;, 
        &#39;charset&#39; => &#39;utf8&#39;, 
        &#39;tablePrefix&#39; => &#39;xcpt_&#39;, //表前缀 
        &#39;enableSlave&#39;=>true,//从数据库启用 
   &#39;urgencyWrite&#39;=>true,//紧急情况 主数据库无法连接 启用从数据库 写功能 
    &#39;masterRead&#39;=>true,//紧急情况 从数据库无法连接 启用主数据库 读功能 
        &#39;slaves&#39;=>array(//从数据库 
            array(   //slave1 
                &#39;connectionString&#39;=>&#39;mysql:host=localhost;dbname=db_xcpt&#39;, 
                &#39;emulatePrepare&#39; => true, 
                &#39;username&#39;=>&#39;root&#39;, 
                &#39;password&#39;=>&#39;root&#39;, 
                &#39;charset&#39; => &#39;utf8&#39;, 
                &#39;tablePrefix&#39; => &#39;xcpt_&#39;, //表前缀 
            ), 
   array(   //slave2 
                &#39;connectionString&#39;=>&#39;mysql:host=localhost;dbname=db_xcpt&#39;, 
                &#39;emulatePrepare&#39; => true, 
                &#39;username&#39;=>&#39;root&#39;, 
                &#39;password&#39;=>&#39;root&#39;, 
                &#39;charset&#39; => &#39;utf8&#39;, 
                &#39;tablePrefix&#39; => &#39;xcpt_&#39;, //表前缀 
            ), 
 
        ), 
),


Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
PHP Performance Tuning for High Traffic WebsitesPHP Performance Tuning for High Traffic WebsitesMay 14, 2025 am 12:13 AM

ThesecrettokeepingaPHP-poweredwebsiterunningsmoothlyunderheavyloadinvolvesseveralkeystrategies:1)ImplementopcodecachingwithOPcachetoreducescriptexecutiontime,2)UsedatabasequerycachingwithRedistolessendatabaseload,3)LeverageCDNslikeCloudflareforservin

Dependency Injection in PHP: Code Examples for BeginnersDependency Injection in PHP: Code Examples for BeginnersMay 14, 2025 am 12:08 AM

You should care about DependencyInjection(DI) because it makes your code clearer and easier to maintain. 1) DI makes it more modular by decoupling classes, 2) improves the convenience of testing and code flexibility, 3) Use DI containers to manage complex dependencies, but pay attention to performance impact and circular dependencies, 4) The best practice is to rely on abstract interfaces to achieve loose coupling.

PHP Performance: is it possible to optimize the application?PHP Performance: is it possible to optimize the application?May 14, 2025 am 12:04 AM

Yes,optimizingaPHPapplicationispossibleandessential.1)ImplementcachingusingAPCutoreducedatabaseload.2)Optimizedatabaseswithindexing,efficientqueries,andconnectionpooling.3)Enhancecodewithbuilt-infunctions,avoidingglobalvariables,andusingopcodecaching

PHP Performance Optimization: The Ultimate GuidePHP Performance Optimization: The Ultimate GuideMay 14, 2025 am 12:02 AM

ThekeystrategiestosignificantlyboostPHPapplicationperformanceare:1)UseopcodecachinglikeOPcachetoreduceexecutiontime,2)Optimizedatabaseinteractionswithpreparedstatementsandproperindexing,3)ConfigurewebserverslikeNginxwithPHP-FPMforbetterperformance,4)

PHP Dependency Injection Container: A Quick StartPHP Dependency Injection Container: A Quick StartMay 13, 2025 am 12:11 AM

APHPDependencyInjectionContainerisatoolthatmanagesclassdependencies,enhancingcodemodularity,testability,andmaintainability.Itactsasacentralhubforcreatingandinjectingdependencies,thusreducingtightcouplingandeasingunittesting.

Dependency Injection vs. Service Locator in PHPDependency Injection vs. Service Locator in PHPMay 13, 2025 am 12:10 AM

Select DependencyInjection (DI) for large applications, ServiceLocator is suitable for small projects or prototypes. 1) DI improves the testability and modularity of the code through constructor injection. 2) ServiceLocator obtains services through center registration, which is convenient but may lead to an increase in code coupling.

PHP performance optimization strategies.PHP performance optimization strategies.May 13, 2025 am 12:06 AM

PHPapplicationscanbeoptimizedforspeedandefficiencyby:1)enablingopcacheinphp.ini,2)usingpreparedstatementswithPDOfordatabasequeries,3)replacingloopswitharray_filterandarray_mapfordataprocessing,4)configuringNginxasareverseproxy,5)implementingcachingwi

PHP Email Validation: Ensuring Emails Are Sent CorrectlyPHP Email Validation: Ensuring Emails Are Sent CorrectlyMay 13, 2025 am 12:06 AM

PHPemailvalidationinvolvesthreesteps:1)Formatvalidationusingregularexpressionstochecktheemailformat;2)DNSvalidationtoensurethedomainhasavalidMXrecord;3)SMTPvalidation,themostthoroughmethod,whichchecksifthemailboxexistsbyconnectingtotheSMTPserver.Impl

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software