Nodejs 事务问题
Nodejs 事务问题
代码如下:
var mysql = require('mysql');
var conn = mysql.createConnection({
host:'localhost',
user:'root',
password:'',
database:'cluster_manager_dev',
port:3306
});
conn.beginTransaction(function(err) {
if(err) {
throw err;
console.log(err);
}
conn.query('insert into user set user_name = ?, password = ?, is_admin = ?', ['testkjk', '123456', '2'], function(err, result) {
if(err) {
conn.rollback(function() {
console.log('first insert into user');
throw err;
});
}
conn.query('insert into user', function(err, result) {
if(err) {
console.log('second insert into user');
conn.rollback(function() {
throw err;
});
}
conn.commit(function(err) {
console.log('enter the commit');
if(err) {
conn.rollback(function() {
throw err;
});
}
console.log('success');
});
});
});
});
最终的结果第一条语句执行了,向数据库中插入了testkjk,而且程序也打印了 second insert into user, 而没有回滚,这是为什么呢?
附上程序执行错误输出:
second insert into user
Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
at Query.Sequence._packetToError (/usr/local/NArk/web/node_modules/mysql/lib/protocol/sequences/Sequence.js:32:14)
at Query.ErrorPacket (/usr/local/NArk/web/node_modules/mysql/lib/protocol/sequences/Query.js:82:18)
at Protocol._parsePacket (/usr/local/NArk/web/node_modules/mysql/lib/protocol/Protocol.js:177:24)
at Parser.write (/usr/local/NArk/web/node_modules/mysql/lib/protocol/Parser.js:62:12)
at Protocol.write (/usr/local/NArk/web/node_modules/mysql/lib/protocol/Protocol.js:37:16)
at Socket.ondata (stream.js:51:26)
at Socket.emit (events.js:117:20)
at Socket.<anonymous> (_stream_readable.js:748:14)
at Socket.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:410:10)
--------------------
at Query.Sequence (/usr/local/NArk/web/node_modules/mysql/lib/protocol/sequences/Sequence.js:15:20)
at new Query (/usr/local/NArk/web/node_modules/mysql/lib/protocol/sequences/Query.js:12:12)
at Function.Connection.createQuery (/usr/local/NArk/web/node_modules/mysql/lib/Connection.js:47:10)
at Connection.query (/usr/local/NArk/web/node_modules/mysql/lib/Connection.js:131:26)
at Query._callback (/usr/local/NArk/web/test.js:24:8)
at Query.Sequence.end (/usr/local/NArk/web/node_modules/mysql/lib/protocol/sequences/Sequence.js:75:24)
at Query._handleFinalResultPacket (/usr/local/NArk/web/node_modules/mysql/lib/protocol/sequences/Query.js:143:8)
at Query.OkPacket (/usr/local/NArk/web/node_modules/mysql/lib/protocol/sequences/Query.js:77:10)
at Protocol._parsePacket (/usr/local/NArk/web/node_modules/mysql/lib/protocol/Protocol.js:177:24)
at Parser.write (/usr/local/NArk/web/node_modules/mysql/lib/protocol/Parser.js:62:12)
Nodejs 事务问题
问题描述
你提到的代码中使用了MySQL事务来处理两个插入操作。然而,在实际运行时,第一个插入操作成功执行,而第二个插入操作却失败了,并且没有触发回滚操作。
问题原因
问题在于第二个插入操作的SQL语句有语法错误。从错误信息可以看出,第二个插入操作的SQL语句为空:
Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
这表明第二个插入操作的SQL语句 conn.query('insert into user')
是无效的,因为它没有任何具体的值或条件。
解决方案
为了正确地处理事务并确保在发生错误时能够回滚,你需要确保每个SQL语句都是有效的。以下是修正后的代码示例:
var mysql = require('mysql');
var conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'cluster_manager_dev',
port: 3306
});
conn.beginTransaction(function (err) {
if (err) {
throw err;
}
conn.query('INSERT INTO user SET user_name = ?, password = ?, is_admin = ?', ['testkjk', '123456', '2'], function (err, result) {
if (err) {
conn.rollback(function () {
console.log('First insert into user failed');
throw err;
});
}
// Corrected SQL query with values
conn.query('INSERT INTO user SET user_name = ?, password = ?, is_admin = ?', ['testuser', 'password123', '0'], function (err, result) {
if (err) {
console.log('Second insert into user failed');
conn.rollback(function () {
throw err;
});
} else {
conn.commit(function (err) {
if (err) {
conn.rollback(function () {
throw err;
});
}
console.log('Transaction committed successfully');
});
}
});
});
});
解释
- 事务开始:通过
beginTransaction()
开始一个事务。 - 第一个插入操作:插入一条用户记录。
- 第二个插入操作:修正了SQL语句,确保它包含具体的值。
- 错误处理:
- 如果第一个插入操作失败,则调用
rollback()
回滚事务。 - 如果第二个插入操作失败,则同样调用
rollback()
回滚事务。
- 如果第一个插入操作失败,则调用
- 提交事务:如果所有操作都成功,则调用
commit()
提交事务。
这样可以确保只有当所有操作都成功时才会提交事务,否则会回滚事务以保持数据的一致性。
if( err ) { ..... ;return; }
rollback
之后要return
,不然后面的语句会继续执行
事务处理建议使用 bearcat-dao 吧,这样子太原始了,业务逻辑和事务代码耦合在一起
问题解决了,没设置innoDB,太2了。。。
根据你的描述和代码,错误发生在第二条插入语句。具体来看,错误信息指出 ER_PARSE_ERROR
,即SQL语法错误。错误提示是由于第二条插入语句没有正确的SQL语法。
问题分析
在代码中的第二条插入语句是:
conn.query('insert into user', function(err, result) {
这条语句没有指定要插入的数据,因此MySQL认为它是一个不完整的查询,导致了语法错误。
解决方案
你需要指定插入的列和值。修改后的代码应该类似于:
conn.query('INSERT INTO user (column1, column2) VALUES (?, ?)', ['value1', 'value2'], function(err, result) {
// 处理错误和结果
});
示例代码
下面是修复后的完整示例代码:
var mysql = require('mysql');
var conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'cluster_manager_dev',
port: 3306
});
conn.beginTransaction(function(err) {
if (err) {
throw err;
}
conn.query('INSERT INTO user (user_name, password, is_admin) VALUES (?, ?, ?)', ['testkjk', '123456', '2'], function(err, result) {
if (err) {
conn.rollback(function() {
console.log('first insert into user');
throw err;
});
} else {
conn.query('INSERT INTO user (user_name, password, is_admin) VALUES (?, ?, ?)', ['testkjk2', '123456', '2'], function(err, result) {
if (err) {
console.log('second insert into user');
conn.rollback(function() {
throw err;
});
} else {
conn.commit(function(err) {
if (err) {
conn.rollback(function() {
throw err;
});
}
console.log('success');
});
}
});
}
});
});
总结
确保每一条插入语句都包含完整的插入语法,并且处理好错误和回滚逻辑,以保证事务的一致性。