资讯专栏INFORMATION COLUMN

thinkphp 下数据库读写分离代码剖析

sunsmell / 1183人阅读

摘要:核心类中,方法,调用查询是否需要解析调用执行查询返回数据集指令存储过程查询支持释放前次的查询结果记录开始执行时间上面初始化数据库链接时,,调用注意代码实现。表示直接调用主库,表示调用读写分离的读库。

当采用原生态的sql语句进行写入操作的时候,要用execute,读操作要用query。

MySQL数据主从同步还是要靠MySQL的机制来实现,所以这个时候MySQL主从同步的延迟问题是需要优化,延迟时间太长不仅影响业务,还影响用户体验。

thinkphp核心类Thinkphp/library/Model.class.php 中,query 方法,

    调用Thinkphp/library/Think/Db/Driver/Mysql.class.php
    /**
     * SQL查询
     * @access public
     * @param string $sql  SQL
     * @param mixed $parse  是否需要解析SQL  
     * @return mixed
     */
    public function query($sql,$parse=false) {
        if(!is_bool($parse) && !is_array($parse)) {
            $parse = func_get_args();
            array_shift($parse);
        }
        $sql  =   $this->parseSql($sql,$parse);
        return $this->db->query($sql);
    }
    调用Thinkphp/library/Think/Db/Driver/Mysql.class.php
    /**
     * 执行查询 返回数据集
     * @access public
     * @param string $str  sql指令
     * @return mixed
     */
    public function query($str) {
        if(0===stripos($str, "call")){ // 存储过程查询支持
            $this->close();
            $this->connected    =   false;
        }
        $this->initConnect(false);
        if ( !$this->_linkID ) return false;
        $this->queryStr = $str;
        //释放前次的查询结果
        if ( $this->queryID ) {    $this->free();    }
        N("db_query",1);
        // 记录开始执行时间
        G("queryStartTime");
        $this->queryID = mysql_query($str, $this->_linkID);
        $this->debug();
        if ( false === $this->queryID ) {
            $this->error();
            return false;
        } else {
            $this->numRows = mysql_num_rows($this->queryID);
            return $this->getAll();
        }
    }

上面初始化数据库链接时,initConnect(false),调用Thinkphp/library/Think/Db/Db.class.php,注意false、true代码实现。true表示直接调用主库,false表示调用读写分离的读库。

    /**
     * 初始化数据库连接
     * @access protected
     * @param boolean $master 主服务器
     * @return void
     */
    protected function initConnect($master=true) {
        if(1 == C("DB_DEPLOY_TYPE"))
            // 采用分布式数据库
            $this->_linkID = $this->multiConnect($master);
        else
            // 默认单数据库
            if ( !$this->connected ) $this->_linkID = $this->connect();
    }

    /**
     * 连接分布式服务器
     * @access protected
     * @param boolean $master 主服务器
     * @return void
     */
    protected function multiConnect($master=false) {
        foreach ($this->config as $key=>$val){
            $_config[$key]      =   explode(",",$val);
        }        
        // 数据库读写是否分离
        if(C("DB_RW_SEPARATE")){
            // 主从式采用读写分离
            if($master)
                // 主服务器写入
                $r  =   floor(mt_rand(0,C("DB_MASTER_NUM")-1));
            else{
                if(is_numeric(C("DB_SLAVE_NO"))) {// 指定服务器读
                    $r = C("DB_SLAVE_NO");
                }else{
                    // 读操作连接从服务器
                    $r = floor(mt_rand(C("DB_MASTER_NUM"),count($_config["hostname"])-1));   // 每次随机连接的数据库
                }
            }
        }else{
            // 读写操作不区分服务器
            $r = floor(mt_rand(0,count($_config["hostname"])-1));   // 每次随机连接的数据库
        }
        $db_config = array(
            "username"  =>  isset($_config["username"][$r])?$_config["username"][$r]:$_config["username"][0],
            "password"  =>  isset($_config["password"][$r])?$_config["password"][$r]:$_config["password"][0],
            "hostname"  =>  isset($_config["hostname"][$r])?$_config["hostname"][$r]:$_config["hostname"][0],
            "hostport"  =>  isset($_config["hostport"][$r])?$_config["hostport"][$r]:$_config["hostport"][0],
            "database"  =>  isset($_config["database"][$r])?$_config["database"][$r]:$_config["database"][0],
            "dsn"       =>  isset($_config["dsn"][$r])?$_config["dsn"][$r]:$_config["dsn"][0],
            "params"    =>  isset($_config["params"][$r])?$_config["params"][$r]:$_config["params"][0],
            "charset"   =>  isset($_config["charset"][$r])?$_config["charset"][$r]:$_config["charset"][0],            
        );
        return $this->connect($db_config,$r);
    }

query方法参数为false,其他删除、更新、增加读主库。这一点可以结合Thinkphp/library/Model.class.php中的delete、save、add操作,参数为true。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22777.html

相关文章

  • thinkphp 据库读写分离代码剖析

    摘要:核心类中,方法,调用查询是否需要解析调用执行查询返回数据集指令存储过程查询支持释放前次的查询结果记录开始执行时间上面初始化数据库链接时,,调用注意代码实现。表示直接调用主库,表示调用读写分离的读库。 当采用原生态的sql语句进行写入操作的时候,要用execute,读操作要用query。 MySQL数据主从同步还是要靠MySQL的机制来实现,所以这个时候MySQL主从同步的延迟问题是需...

    KavenFan 评论0 收藏0
  • ThinkPHP 3.2 性能优化,实现高性能API开发

    摘要:目前的业务访问量数千万,后端台,平均使用率。产生的问题长连接数超过时,性能会下降。很可惜,我们目前使用的青云,目前尚不能实现超高可用,也不能实现无缝扩容,私网内的网络传输性能延迟都有很大优化空间。经测试,性能有的提升。 需求分析 目前的业务全站使用ThinkPHP 3.2.3,前台、后台、Cli、Api等。目前的业务API访问量数千万,后端7台PHP 5.6,平均CPU使用率20%。 ...

    siberiawolf 评论0 收藏0
  • ThinkPHP 3.2 性能优化,实现高性能API开发

    摘要:目前的业务访问量数千万,后端台,平均使用率。产生的问题长连接数超过时,性能会下降。很可惜,我们目前使用的青云,目前尚不能实现超高可用,也不能实现无缝扩容,私网内的网络传输性能延迟都有很大优化空间。经测试,性能有的提升。 需求分析 目前的业务全站使用ThinkPHP 3.2.3,前台、后台、Cli、Api等。目前的业务API访问量数千万,后端7台PHP 5.6,平均CPU使用率20%。 ...

    Chao 评论0 收藏0
  • 开源:vue2和thinkphp搭建的前后端分离项目

    摘要:大学生论坛采用和搭建的前后端分离项目地址项目说明本项目为前后端分离项目前端采用全家桶包括搭建,请求采用,组件采用,对象存储采用七牛云需要自己配置,实现客户端上传图片,目前已完成功能用户登录注册用户中心基于的富文本发布。 大学生论坛 采用vue2和thinkphp搭建的前后端分离项目 github地址:https://github.com/lll618xxx/... showImg(ht...

    Allen 评论0 收藏0
  • 开源:vue2和thinkphp搭建的前后端分离项目

    摘要:大学生论坛采用和搭建的前后端分离项目地址项目说明本项目为前后端分离项目前端采用全家桶包括搭建,请求采用,组件采用,对象存储采用七牛云需要自己配置,实现客户端上传图片,目前已完成功能用户登录注册用户中心基于的富文本发布。 大学生论坛 采用vue2和thinkphp搭建的前后端分离项目 github地址:https://github.com/lll618xxx/... showImg(ht...

    Tikitoo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<