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)

7 回复

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');
                });
            }
        });
    });
});

解释

  1. 事务开始:通过 beginTransaction() 开始一个事务。
  2. 第一个插入操作:插入一条用户记录。
  3. 第二个插入操作:修正了SQL语句,确保它包含具体的值。
  4. 错误处理
    • 如果第一个插入操作失败,则调用 rollback() 回滚事务。
    • 如果第二个插入操作失败,则同样调用 rollback() 回滚事务。
  5. 提交事务:如果所有操作都成功,则调用 commit() 提交事务。

这样可以确保只有当所有操作都成功时才会提交事务,否则会回滚事务以保持数据的一致性。


忘了附上mysql版本 node-mysql@2.0.0-rc1

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');
                    });
                }
            });
        }
    });
});

总结

确保每一条插入语句都包含完整的插入语法,并且处理好错误和回滚逻辑,以保证事务的一致性。

回到顶部