# Mysql [TOC] SD提供了Mysql异步连接池。这里提供3.1版本全新的API,新版Mysql支持SQL预处理请求,不用再担心安全问题了。 ## 迁移指南 之前的版本迁移到新版时需要注意: 1. coroutineSend已经被弃用,更换为query。 2. 事务已改版 ``` public function query($sql = null, callable $set = null) ``` ## 创建Mysql连接池 在SD的initAsynPools方法中已经创建好了redis和mysql默认的连接池。 ``` /** * 初始化各种连接池 * @param $workerId */ public function initAsynPools($workerId) { $this->asynPools = []; if ($this->config->get('redis.enable', true)) { $this->asynPools['redisPool'] = new RedisAsynPool($this->config, $this->config->get('redis.active')); } if ($this->config->get('mysql.enable', true)) { $this->asynPools['mysqlPool'] = new MysqlAsynPool($this->config, $this->config->get('mysql.active')); } $this->redis_pool = $this->asynPools['redisPool'] ?? null; $this->mysql_pool = $this->asynPools['mysqlPool'] ?? null; } ``` 如果你想创建多个Mysql连接池可以仿照上面的方法。 ``` $this->addAsynPool('mysqlPool2', new MysqlAsynPool($this->config, ‘mysql2’); ``` ## 获取Mysql连接池 在Controller,Model,Task中默认获取了MysqlPool。 ``` /** * 当被loader时会调用这个方法进行初始化 * @param $context */ public function initialization(&$context) { $this->setContext($context); $this->redis = $this->loader->redis("redisPool"); $this->db = $this->loader->mysql("mysqlPool",$this); } ``` ### 返回结构 通过query默认会返回一个数组。 ``` { "result": [ ], "affected_rows": 0, "insert_id": 0, "client_id": 0 } ``` result是返回的结果必定是个数组,affected_rows影响的行数,insert_id插入的id。 ### 直接执行sql ``` $this->db->query(" CREATE TABLE IF NOT EXISTS `MysqlTest` ( `peopleid` smallint(6) NOT NULL AUTO_INCREMENT, `firstname` char(50) NOT NULL, `lastname` char(50) NOT NULL, `age` smallint(6) NOT NULL, `townid` smallint(6) NOT NULL, PRIMARY KEY (`peopleid`), UNIQUE KEY `unique_fname_lname`(`firstname`,`lastname`), KEY `fname_lname_age` (`firstname`,`lastname`,`age`) ) ; "); ``` ### Select ``` $value = $this->db->Select('*') ->from('MysqlTest') ->where('townid', 10000)->query(); ``` ### Update ``` $value = $this->db->update('MysqlTest') ->set('age', '20') ->where('townid', 10000)->query(); ``` ### Update 字段值的增加/减少 ``` $value = $this->db->update('MysqlTest') ->set("score","score+1",false) ->where('townid', 10000)->query(); ``` ### Replace ``` $value = $this->mysql_pool->dbQueryBuilder->replace('MysqlTest') ->set('firstname', 'White') ->set('lastname', 'Cat') ->set('age', '26') ->set('townid', '10000')->query(); ``` ### Delete ``` $value = $this->mysql_pool->dbQueryBuilder->delete() ->from('MysqlTest') ->where('townid', 10000)->query(); ``` ### Raw混合SQL ``` $selectMiner = $this->db->select('*')->from('account'); $selectMiner = $selectMiner->where('', '(status = 1 and dec in ("ss", "cc")) or name = "kk"', Miner::LOGICAL_RAW)->query(); ``` ### 获取SQL命令 ``` $value = $this->db->insertInto('account')->intoColumns(['uid', 'static'])->intoValues([[36, 0], [37, 0]])->getStatement(true); ``` 通过getStatement可以获取构建器构建的sql语法。 ### insertInto,updateInto,replaceInto 批量操作 ``` $value = $this->db->insertInto('account')->intoColumns(['uid', 'static'])->intoValues([[36, 0], [37, 0]])->query(); ``` 批量命令配合intoColumns和intoValues设置批量操作 ### 超时 超时设置 ``` $result = $this->db->select('*')->from('account')->limit(1)->query(null,function (MySqlCoroutine $mySqlCoroutine){ $mySqlCoroutine->setTimeout(1000); $mySqlCoroutine->noException("test"); $mySqlCoroutine->dump(); }); echo $result->num_rows(); ``` 除了超时Mysql提供了一些其他的API * result_array 直接返回result * row_array 返回某一个 * row 返回第一个 * num_rows 返回数量 * insert_id 返回insert_id * dump 打印执行的sql命令 ### 事务 begin开启一个事务,在回调中执行事务,如果抛出异常则自动回滚,如果正常则自动提交。 ``` public function http_mysql_begin_coroutine_test() { $this->db->begin(function () { $result = $this->db->select("*")->from("account")->query(); var_dump($result['client_id']); $result = $this->db->select("*")->from("account")->query(); var_dump($result['client_id']); }); $this->http_output->end(1); } ``` ### 同步Mysql ``` $mysqlSync = $this->mysql_pool->getSync(); ``` 通过getSync返回一个同步PDO的mysql连接。 同步mysql可以使用pdo开头的方法。 * pdoQuery * pdoBeginTrans * pdoCommitTrans * pdoRollBackTrans * pdoInsertId