# Workerman/MySQL
## 說明
常駐內存的程序在使用mysql時經常會遇到```mysql gone away```的錯誤,這個是由于程序與mysql的連接長時間沒有通訊,連接被mysql服務端踢掉導致。本數據庫類可以解決這個問題,當發生```mysql gone away```錯誤時,會自動重試一次。
## 依賴的擴展
該mysql類依賴[pdo](http://php.net/manual/zh/book.pdo.php)和[pdo\_mysql](http://php.net/manual/zh/ref.pdo-mysql.php)兩個擴展,缺少擴展會報```Undefined class constant 'MYSQL\_ATTR\_INIT\_COMMAND' in ....```錯誤。
命令行運行```php -m```會列出所有php cli已安裝的擴展,如果沒有pdo 或者 pdo\_mysql,請自行安裝。
**centos系統**
PHP5.x
```php
yum install php-pdo
yum install php-mysql
```
PHP7.x
```php
yum install php70w-pdo_dblib.x86_64
yum install php70w-mysqlnd.x86_64
```
如果找不到包名,請嘗試用```yum search php mysql```查找
**ubuntu/debian系統**
PHP5.x
```php
apt-get install php5-mysql
```
PHP7.x
```php
apt-get install php7.0-mysql
```
如果找不到包名,請嘗試用```apt-cache search php mysql```查找
**以上方法無法安裝?**
如果以上方法無法安裝,請參考[workerman手冊-附錄-擴展安裝-方法三源碼編譯安裝](315304)。
## 安裝 Workerman/MySQL
**方法1:**
可以通過composer安裝,命令行運行以下命令(composer源在國外,安裝過程可能會非常慢)。
```php
composer require workerman/mysql
```
上面命令成功后會生成vendor目錄,然后在項目中引入vendor下的autoload.php。
```php
require_once __DIR__ . '/vendor/autoload.php';
```
**方法2:**
[下載源碼](https://github.com/walkor/mysql/archive/master.zip),解壓后的目錄放到自己項目中(位置任意),直接require源文件。
```php
require_once '/your/path/of/mysql-master/src/Connection.php';
```
## 注意
強烈建議在onWorkerStart回調中初始化數據庫連接,避免在```Worker::runAll();```運行前就初始化連接,在```Worker::runAll();```運行前初始化的連接屬于主進程,子進程會繼承這個連接,主進程和子進程共用相同的數據庫連接會導致的錯誤。
## 示例
```php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('websocket://0.0.0.0:8484');
$worker->onWorkerStart = function($worker)
{
// 將db實例存儲在全局變量中(也可以存儲在某類的靜態成員中)
global $db;
$db = new Workerman\MySQL\Connection('host', 'port', 'user', 'password', 'db_name');
};
$worker->onMessage = function($connection, $data)
{
// 通過全局變量獲得db實例
global $db;
// 執行SQL
$all_tables = $db->query('show tables');
$connection->send(json_encode($all_tables));
};
// 運行worker
Worker::runAll();
```
## 具體MySQL/Connection用法
```php
// 初始化db連接
$db = new Workerman\MySQL\Connection('host', 'port', 'user', 'password', 'db_name');
// 獲取所有數據
$db->select('ID,Sex')->from('Persons')->where('sex= :sex AND ID = :id')->bindValues(array('sex'=>'M', 'id' => 1))->query();
//等價于
$db->select('ID,Sex')->from('Persons')->where("sex= 'M' AND ID = 1")->query();
//等價于
$db->query("SELECT ID,Sex FROM `Persons` WHERE sex='M' AND ID = 1");
// 獲取一行數據
$db->select('ID,Sex')->from('Persons')->where('sex= :sex')->bindValues(array('sex'=>'M'))->row();
//等價于
$db->select('ID,Sex')->from('Persons')->where("sex= 'M' ")->row();
//等價于
$db->row("SELECT ID,Sex FROM `Persons` WHERE sex='M'");
// 獲取一列數據
$db->select('ID')->from('Persons')->where('sex= :sex')->bindValues(array('sex'=>'M'))->column();
//等價于
$db->select('ID')->from('Persons')->where("sex= 'F' ")->column();
//等價于
$db->column("SELECT `ID` FROM `Persons` WHERE sex='M'");
// 獲取單個值
$db->select('ID,Sex')->from('Persons')->where('sex= :sex')->bindValues(array('sex'=>'M'))->single();
//等價于
$db->select('ID,Sex')->from('Persons')->where("sex= 'F' ")->single();
//等價于
$db->single("SELECT ID,Sex FROM `Persons` WHERE sex='M'");
// 復雜查詢
$db->select('*')->from('table1')->innerJoin('table2','table1.uid = table2.uid')->where('age > :age')->groupBy(array('aid'))->having('foo="foo"')->orderByASC/*orderByDESC*/(array('did'))
->limit(10)->offset(20)->bindValues(array('age' => 13));
// 等價于
$db->query(SELECT * FROM `table1` INNER JOIN `table2` ON `table1`.`uid` = `table2`.`uid`
WHERE age > 13 GROUP BY aid HAVING foo="foo" ORDER BY did LIMIT 10 OFFSET 20“);
// 插入
$insert_id = $db->insert('Persons')->cols(array(
'Firstname'=>'abc',
'Lastname'=>'efg',
'Sex'=>'M',
'Age'=>13))->query();
等價于
$insert_id = $db->query("INSERT INTO `Persons` ( `Firstname`,`Lastname`,`Sex`,`Age`)
VALUES ( 'abc', 'efg', 'M', 13)");
// 更新
$row_count = $db->update('Persons')->cols(array('sex'))->where('ID=1')
->bindValue('sex', 'F')->query();
// 等價于
$row_count = $db->update('Persons')->cols(array('sex'=>'F'))->where('ID=1')->query();
// 等價于
$row_count = $db->query("UPDATE `Persons` SET `sex` = 'F' WHERE ID=1");
// 刪除
$row_count = $db->delete('Persons')->where('ID=9')->query();
// 等價于
$row_count = $db->query("DELETE FROM `Persons` WHERE ID=9");
// 事務
$db->beginTrans();
....
$db->commitTrans(); // or $db->rollBackTrans();
```
- 序言
- 原理
- 開發必讀
- 入門指引
- 特性
- 簡單的開發示例
- 安裝
- 環境要求
- 下載安裝
- 啟動停止
- 開發流程
- 開發前必讀
- 目錄結構
- 開發規范
- 基本流程
- 通訊協議
- 通訊協議作用
- 定制通訊協議
- 一些例子
- Worker類
- 構造函數
- 屬性
- id
- count
- name
- protocol
- transport
- reusePort
- connections
- stdoutFile
- pidFile
- logFile
- user
- reloadable
- daemonize
- globalEvent
- 回調屬性
- onWorkerStart
- onWorkerReload
- onConnect
- onMessage
- onClose
- onBufferFull
- onBufferDrain
- onError
- 接口
- runAll
- stopAll
- listen
- TcpConnection類
- 屬性
- id
- protocol
- worker
- maxSendBufferSize
- defaultMaxSendBufferSize
- maxPackageSize
- 回調屬性
- onMessage
- onClose
- onBufferFull
- onBufferDrain
- onError
- 接口
- send
- getRemoteIp
- getRemotePort
- close
- destroy
- pauseRecv
- resumeRecv
- pipe
- AsyncTcpConnection類
- 構造函數
- connect
- reconnect
- transport
- Timer定時器類
- add
- del
- 定時器注意事項
- WebServer
- 調試
- 基本調試
- 查看運行狀態
- 網絡抓包
- 跟蹤系統調用
- 常用組件
- GlobalData數據共享組件
- GlobalDataServer
- GlobalDataClient
- Channel分布式通訊組件
- ChannelServer
- channelClient
- 例子-集群推送
- 例子-分組發送
- FileMonitor文件監控組件
- MySQL組件
- workerman/mysql
- swoole/mysql(異步)
- redis組件
- swoole/redis
- 異步http組件
- swoole/http-client
- 異步消息隊列組件
- react/zmq
- react/stomp
- 異步dns組件
- swoole/dns
- 常見問題
- 心跳
- 客戶端鏈接失敗原因
- 是否支持多線程
- 與其它框架整合
- 運行多個workerman
- 支持哪些協議
- 如何設置進程數
- 查看客戶端連接數
- 對象和資源的持久化
- 例子無法工作
- 啟動失敗
- 停止失敗
- 支持多少并發
- 更改代碼不生效
- 向指定客戶端發送數據
- 如何主動推送消息
- 在其它項目中推送
- 如何實現異步任務
- status里send_fail的原因
- Windows下開發Linux下部署
- 是否支持socket.io
- 終端關閉導致workerman關閉
- 與nginx apache的關系
- 禁用函數檢查
- 平滑重啟原理
- 為Flash開843端口
- 如何廣播數據
- 如何建立udp服務
- 監聽ipv6
- 關閉未認證的鏈接
- 傳輸加密-ssl/tsl
- 創建wss服務
- 創建https服務
- workerman作為客戶端
- 作為ws/wss客戶端
- PHP的幾種回調寫法
- 附錄
- Linux內核調優
- 壓力測試
- 安裝擴展
- websocket協議
- ws協議
- text協議
- frame協議
- 不支持的函數/特性
- 版權信息