mysql2/promise:INSERT语句在事务查询中无效



感谢您抽出时间。我在使用mysql2/promise包创建事务查询时遇到了问题。

以下是查询:

    await db.execute(`START TRANSACTION`);
    await db.execute(`INSERT INTO user VALUES (?, ?, ?, ?, ?, ?)`, [...userDetails]);
    await db.execute(`INSERT INTO account VALUES (?, ?, ?, ?, ?, ?)`, [...accountDetails]);
    await db.execute(`COMMIT`);

我得到的错误是:

Error: This command is not supported in the prepared statement protocol yet
code: 'ER_UNSUPPORTED_PS',
  errno: 1295,
  sql: 'START TRANSACTION',
  sqlState: 'HY000',
  sqlMessage: 'This command is not supported in the prepared statement protocol yet'

我想知道是否与我的查询有关?我认为INSERT语句在事务块中应该非常好。我还尝试将每个查询组合成一个字符串,但这似乎也不起作用。

MySQL限制了哪些语句可以在准备好的语句中完成,不允许使用start transaction。请参阅Prepared Statements中允许的SQL语法,这里有一个演示。

execute总是使用和缓存准备好的语句。如果查询很复杂(MySQL不必每次都解析它(或需要参数(为了安全起见(,这是很好的。

但是,如果您的查询很简单,并且不接受任何参数,则无需准备它。请使用仅运行SQL的query。这既避免了出现错误,又避免了填满准备好的语句缓存。

    await db.query(`START TRANSACTION`);
    await db.execute(`INSERT INTO user VALUES (?, ?, ?, ?, ?, ?)`, [...userDetails]);
    await db.execute(`INSERT INTO account VALUES (?, ?, ?, ?, ?, ?)`, [...accountDetails]);
    await db.query(`COMMIT`);

我认为这个问题的答案是正确的,但代码(示例(不是,也不应该使用。尽管这些语句可能有效,但它不会创建有效的事务,因为可能已经建立了与数据库的新连接。

正确的方法是获得一个连接句柄:

let conn = await this.getConnection();
await conn.query('START TRANSACTION');
// do your stuff here
await conn.execute('...')'
await conn.query('COMMIT');
conn.release();

这确保了一个有效的事务(START和COMMIT应该在同一个连接上(。除非只指定了一个连接,否则直接调用数据库对象并不能提供这种保证。

相关内容

  • 没有找到相关文章

最新更新