無論是node.js 還是 mysql 對我來說都並不陌生,然而我還真的是第一次將它們組合起來使用,初用node.js 的時候就接受了MongoDB,之後也很少用mysql了。
本文面向對 node.js 與 mysql 有基本瞭解,試圖組合使用他們的讀者(也包括我自己)。
安裝
非常簡單,準確地說並不是安裝mysql數據庫的本體,而是指mysql到nodejs的驅動程序。
使用 npm 在項目目錄安裝即可:
$ npm install mysql --save
連接
也是非常簡單,先引入這個mysql包,然後調用 createConnection
方法來創建一個Connection對象。
參數細節可以參考:node mysql - Connection options
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'test'
});
現在這個 connection
還沒有真正建立與數據庫的連接。
你可以顯式地調用 connection.connect()
來建立連接,或者:
// 查詢所有的數據表
connection.query('show tables', (err, res) => console.log(err, res));
However, a connection can also be implicitly established by invoking a query
然而,數據庫連接可以在調用查詢時被隱式建立。—— node-mysql 文檔
真是太方便啦!
連接管理
對於 node.js 應用而言,你大可不必在每次處理客戶端請求的時候建立一個新的連接,然後在處理完畢的關閉這個連接。
你完全可以在整個 node.js 服務器運行時裏面使用一個數據庫連接,不用顯式地調用 connection.close()
來關閉它,除非你確認這個連接在短時間內確實用不到了。
思考1:當node.js 服務器進程結束的時候,若不顯式調用
connection.close()
,mysql服務器中的連接會變成殭屍進程嗎?
不會。mysql服務器與 node.js 服務器之間使用 TCP 套接字來進行通訊,具有實時性1。即便 node.js 進程崩潰導致來不及進行任何掃尾工作,mysql服務器依然能夠短時間內知道連接被斷開了。思考2:爲什麼某些語言(如PHP)中需要顯式地建立連接、關閉連接呢?
首先,連接無法被共享,PHP中程序跑完就跑完了,整個生命週期就那麼短暫,你就算不顯式關閉這個連接,其他的PHP進程也根本沒有辦法獲取你的連接;其次,mysql進行垃圾連接的回收是需要一定額外代價的,高併發環境下,大量PHP進程建立大量連接,卻不關閉它,這給mysql徒增了很多負擔。
反觀node.js,在整個服務器的運行時間下,通常至少以小時爲單位的運行時間下,僅建立一個mysql連接,不關閉又怎麼了嘛!均攤代價又有多少嘛!
模塊化 工程化
利用 node.js 的模塊管理,這樣的封裝可能是比較好的:
首先在根目錄寫一個 config.js
來保存一些全局性的配置(比如數據庫的賬號、密碼等)。
然後建立一個db.js
專門用來聲明數據庫的連接。
然後再在其他的文件,例如test.js
中調用查詢。
|- config.js
|- db.js
|- test.js
config.js
module.exports = {
db: {
host: 'localhost',
user: 'YOUR_USERNAME',
password: 'YOUR_PASSWORD',
database: 'YOUR_DATABASE_NAME'
}
};
db.js
var mysql = require('mysql');
var dbConfig = require('./config').db;
var connection = mysql.createConnection(dbConfig);
module.exports = connection;
對,我們只需要把這個 connection 對象導出就可以了。
test.js
var db = require('./db');
db.query('show processlist', (err, res) => console.log(err? err: res));
這個db.query
是不是特別地令人舒心?編寫test.js
的時候根本不用管具體這個數據庫是怎麼連接的。
參考資料
- 實際上是利用 ping/pong 通訊的僞實時性,因此具有一定的延遲,具體視情況而定。 ↩