node-mysql操作transactions的實例


關於mysql的事務,可查看上一篇文章未尾>>

先更新一條數據

UPDATE user_info SET userName = 'kk' WHERE userId = 1;

SELECT * FROM user_info
 
現在的數據
 
寫一個事務,只選中前面的語句執行:
 
SET AUTOCOMMIT=0;

START TRANSACTION;
SELECT * FROM user_info FOR UPDATE;
COMMIT;

如果使用node.js執行,控制台上會看到待執行的sql處於等待狀態:
 
上面報錯,是因為超時了。
如果執行commit后,再執行node.js腳本(執行的是一句更新sql--UPDATE user_info SET userName = ‘張一’ WHERE userId = 1)

 

這里主要用到了node-mysql-queues,它需要先安裝node-mysql

可能因為版本問題吧,它的頁面給出的操作方法已經失效了。正確的應該如下:

/**
* Created with JetBrains WebStorm.
*/
var mysql = require('mysql');

var connection = mysql.createConnection({
host : 'localhost',
port : 3306,
user : 'root',
password : '123456',
database : 'test',
charset : 'UTF8_GENERAL_CI',
debug : false
});

connection.connect();

//connection.query('CALL proc_simple(1, @a, @b);', function(err, rows, fields) {
// if (err) {
// throw err;
// }
//
// var results = rows[0];
// var row = results[0];
// console.log("userName:",row.uName, "  count:", row.totalCount);
//});

var queues = require('mysql-queues');
const DEBUG = true;
queues(connection, DEBUG);

var trans = connection.startTransaction();
trans.query("UPDATE user_info SET userName = ? WHERE userId = ?", ["張一", 1], function(err, info) {
if (err) {
throw err;
trans.rollback();
} else {
trans.commit(function(err, info) {
console.log(info);
});
}
});
trans.execute();
console.log('execute');
//connection.end();


它還支持一次執行多條sql,其實就是把sql語句放入一個數組,然后循環執行該數組內的每條SQL。

var q = client.createQueue();
q.query(...);
q.query(...);
q.execute();

正常使用的話,請參考如下的代碼:
var mysql = require('mysql');
var client = mysql.createConnection({//createClient(已失效) -> createConnection
user: 'root',
password: 'root'
});
//Enable mysql-queues
var queues = require('mysql-queues');
const DEBUG = true;
queues(client, DEBUG);
//Start running queries as normal...
client.query(...);

//Now you want a separate queue?
var q = client.createQueue();
q.query(...);
q.query(...);
q.execute();

client.query(...); //Will not execute until all queued queries (and their callbacks) completed.

//Now you want a transaction?
var trans = client.startTransaction();
trans.query("INSERT...", [x, y, z], function(err, info) {
if(err)
trans.rollback();
else
trans.query("UPDATE...", [a, b, c, info.insertId], function(err) {
if(err)
trans.rollback();
else
trans.commit();
});
});
trans.execute();
//No other queries will get executed until the transaction completes
client.query("SELECT ...") //This won't execute until the transaction is COMPLETELY done (including callbacks)

//Or... as of version 0.3.0, you can do this...
var trans = client.startTransaction();
function error(err) {
if(err && trans.rollback) {trans.rollback(); throw err;}
}
trans.query("DELETE...", [x], error);
for(var i = 0; i < n; i++)
trans.query("INSERT...", [ y[i] ], error);
trans.commit(); //Implictly calls resume(), which calls execute()
/* In the case written above, COMMIT is placed at the end of the Queue, yet the
entire transaction can be rolled back if an error occurs. Nesting these queries
was not required. */
 
query方法的實現:
Connection.prototype.query = function(sql, values, cb) {
this._implyConnect();

var options = {};

if (typeof sql === 'object') {
// query(options, cb)
options = sql;
cb = values;
values = options.values;

delete options.values;
} else if (typeof values === 'function') {
// query(sql, cb)
cb = values;
options.sql = sql;
values = undefined;
} else {
// query(sql, values, cb)
options.sql = sql;
options.values = values;
}

options.sql = this.format(options.sql, values || []);

if (!('typeCast' in options)) {
options.typeCast = this.config.typeCast;
}

return this._protocol.query(options, cb);
};
如果第二個參數不是函數,調用format則轉換sql,默認將?替換為數組參數的值(一一對應)
Connection.prototype.format = function(sql, values) {
if (typeof this.config.queryFormat == "function") {
return this.config.queryFormat.call(this, sql, values, this.config.timezone);
}
return SqlString.format(sql, values, this.config.timezone);
};
默認的format方法實現如下:
SqlString.format = function(sql, values, timeZone) {
values = [].concat(values);

return sql.replace(/\?/g, function(match) {
if (!values.length) {
return match;
}

return SqlString.escape(values.shift(), false, timeZone);
});
};
也可以使用自定義的函數進行處理,在創建連接的時候,傳入queryFormat參數即可。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM