当前位置: 首页 > 后端技术 > PHP

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

时间:2023-03-29 15:17:41 PHP

使用原生态sql语句进行写操作时,应使用execute,读操作应使用query。MySQL数据主从同步仍然依赖于MySQL机制,所以此时需要优化MySQL主从同步的延迟问题。延迟时间过长不仅影响业务,也影响用户体验。在thinkphp核心类Thinkphp/library/Model.class.php中,查询方法调用Thinkphp/library/Think/Db/Driver/Mysql.class.php/***SQLquery*@accesspublic*@paramstring$sqlSQL*@parammixed$parse是否解析SQL*@returnmixed*/publicfunctionquery($sql,$parse=false){if(!is_bool($parse)&&!is_array($parse)){$parse=func_get_args();array_shift($解析);$sql=$this->parseSql($sql,$parse);返回$this->db->query($sql);}callThinkphp/library/Think/Db/Driver/Mysql.class.php/***执行查询返回数据集*@accesspublic*@paramstring$strsqlcommand*@returnmixed*/publicfunctionquery($str){if(0===stripos($str,'call')){//存储过程查询支持$this->close();$this->connected=false;}$this->initConnect(false);如果(!$this->_linkID)返回false;$this->queryStr=$str;//释放之前的查询结果if($this->queryID){$this->free();}N('db_query',1);//记录开始执行时间G('queryStartTime');$this->queryID=mysql_query($str,$this->_linkID);$this->调试();如果(false===$this->queryID){$this->error();返回假;}else{$this->numRows=mysql_num_rows($this->queryID);返回$this->getAll();}}上面初始化数据库链接的时候,initConnect(false),调用Thinkphp/library/Think/Db/Db.class.php,注意false和true的代码实现。true表示直接调用主库,false表示调用读写分离的read库。/***初始化数据库连接*@accessprotected*@paramboolean$mastermasterserver*@returnvoid*/protectedfunctioninitConnect($master=true){if(1==C('DB_DEPLOY_TYPE'))//使用分布式数据库$this->_linkID=$this->multiConnect($master);else//默认单个数据库if(!$this->connected)$this->_linkID=$this->connect();}/***连接到分布式服务器*@accessprotected*@paramboolean$mastermainserver*@returnvoid*/protectedfunctionmultiConnect($master=false){foreach($this->configas$key=>$val){$_config[$key]=explode(',',$val);}//数据库是否读写分离if(C('DB_RW_SEPARATE')){//主从采用读写分离if($master)//masterserverwrite$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],'密码'=>isset($_config['密码'][$r])?$_config['密码'][$r]:$_config['密码'][0],'主机名'=>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['数据库'][$r]:$_config['数据库'][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['字符集'][$r]:$_config['字符集'][0],);返回$this->connect($db_config,$r);}query方法参数为false,其他删除,更新,增加主库的读取可以结合thinkphp/library/Model.class.php中的删除,保存,添加操作,参数为true。