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参数即可。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

创建代码生成器可以很简单:如何通过T4模板生成代码?[上篇]

在《基于T4的代码生成方式》中,我对T4模板的组成结构、语法,以及T4引擎的工作原理进行了大体的介绍,并且编写了一个T4模板实现了如何将一个XML转变成C#代码...

8068
来自专栏破晓之歌

Python接入mysql数据库 原

右侧有个database,点开后左上角有个“+”符号,选择Data Source-Mysql

701
来自专栏岑玉海

Hive Tunning(二)优化存储

接着上一章我们讲的hive的连接策略,现在我们讲一下hive的数据存储。 下面是hive支持的数据存储格式,有我们常见的文本,JSON,XML,这里我们主要...

4094
来自专栏哲学驱动设计

Rafy 框架 - 使用 SqlTree 查询

本文介绍如何使用 Rafy 框架中的 Sql Tree 查询: 除了开发者常用的 Linq 查询,Rafy 框架还提供了 Sql 语法树的方式来进行查询。 这种...

2127
来自专栏Vamei实验室

被解放的姜戈02 庄园疑云

上一回说到,姜戈的江湖初体验:如何架设服务器,如何回复http请求,如何创建App。这一回,我们要走入糖果庄园。 数据库是一所大庄园,藏着各种宝贝。一个没有数据...

2225
来自专栏DeveWork

WordPress主题下funtions.php的一段“恶意”代码

不多说了,相信有很多WordPresser都知道这段在WordPress主题下fountions.php的“恶意”代码,之所以为“恶意”加个双引号是想说:其实也...

31210
来自专栏逸鹏说道

SQL Server 使用全文索引进行页面搜索

概述 全文引擎使用全文索引中的信息来编译可快速搜索表中的特定词或词组的全文查询。全文索引将有关重要的词及其位置的信息存储在数据库表的一列或多列中。全文索引是一...

3667
来自专栏云计算教程系列

想熟悉PostgreSQL?这篇就够了

PostgreSQL是自由的对象-关系型数据库服务器,在灵活的BSD风格许可证下发行。它在其他开放源代码数据库系统和专有系统之外,为用户又提供了一种选择。 我们...

2242
来自专栏乐沙弥的世界

SQL*Loader使用方法

SQL*Loader由一个输入控制文件来控制整个装载的相关描述信息,一个或多个数据文件作为原始数据,其详细组成结构包括

982
来自专栏林欣哲

MySQL数据库开发规范知识点速查

数据库设计规范 命名规范 基本设计规范 索引设计规范 字段设计规范 SQL开发规范 操作行为规范 命名规范 对象名称使用小写字母并用下划线分割 禁止使用MySQ...

40911

扫码关注云+社区

领取腾讯云代金券