mysql 连接池、并发事务和@用户变量
mysql connection pool, concurrent transactions and @ user variables
我想弄清楚我在应用程序中使用 mySql 数据库的方式是否有问题。
我是 运行ning nodejs, express, mysql2,使用连接池,多语句查询。
我有多个服务器,运行宁不同的服务,访问同一个数据库。
在每个 mySql 指令集的开头,我设置了一些用户变量来检查用户凭据、最新状态等......在接下来的指令中,我使用这些变量有条件地访问一些数据,或者也做插入,修改数据。
这里涉及不同的参与者(nodejs、mysql2 驱动程序、mysql 规格、innoDb 引擎),我不确定哪个对以下问题有明确的答案:
- 我的多语句查询中的所有指令是否会一次性 运行,或者我是否需要担心来自不同查询 and/or 服务器的不同指令交错?
- 每个连接都维护用户变量。如果指令可以交错,我最终可能会遇到不同的事务,这些事务会弄乱彼此的用户变量。将查询包装在
START TRANSACTION; .... COMMIT;
中可以解决问题吗?
现在,我的查询的高级视图是:
const mysql2 = require('mysql2');
const pool = mysql2.createPool({
multipleStatements: 'true',
// other options...
}).promise();
[rows, fields] = await pool.query(`
// Clear variables, in case no result in found in following SELECT:
SET @enable=NULL, @status=NULL, ...;
// Check credentials, status, others:
SELECT blah_blah INTO @enable FROM ...
SELECT more_blah INTO @status FROM ...
//Do stuff based on these variables
SELECT some_stuff FROM somewhere WHERE @enable IS NOT NULL;
INSERT INTO someplace ... // conditioned on @status and others
`);
谢谢!
更好的做法是获取一个连接,并在您 运行 多个语句时保持该连接。这里的答案中有一个完整的示例:
该示例显示了将连接用于具有多个查询的事务,但它也应该可以将该连接用于不属于同一事务的多个语句。或者换句话说,多个事务可以在同一个连接上 运行 在该连接被释放回池之前。
当一个线程持有连接并将其用于连续查询 and/or 事务时,池不会与其他线程共享它。我不是 node.js 开发人员,所以我不知道 node.js 实现的第一手信息,但这是连接池的唯一合理实现。
此外,用户变量和其他会话状态不会泄露给其他线程。当连接返回到池中时,所有会话状态都将被擦除。为了安全起见,这也是连接池实现中应该默认的最佳实践。您不希望将您的银行路由号码存储在用户变量或临时文件中 table,然后发现下一个用户可以读取它,因为他们有机会从池中获取相同的连接。
P.S.: 我从来没有发现任何需要 multipleStatements 选项的案例,MySQL 的前工程总监告诉我:“没有正当理由使用 multi -查询作为一个特征存在。
我想弄清楚我在应用程序中使用 mySql 数据库的方式是否有问题。 我是 运行ning nodejs, express, mysql2,使用连接池,多语句查询。 我有多个服务器,运行宁不同的服务,访问同一个数据库。
在每个 mySql 指令集的开头,我设置了一些用户变量来检查用户凭据、最新状态等......在接下来的指令中,我使用这些变量有条件地访问一些数据,或者也做插入,修改数据。 这里涉及不同的参与者(nodejs、mysql2 驱动程序、mysql 规格、innoDb 引擎),我不确定哪个对以下问题有明确的答案:
- 我的多语句查询中的所有指令是否会一次性 运行,或者我是否需要担心来自不同查询 and/or 服务器的不同指令交错?
- 每个连接都维护用户变量。如果指令可以交错,我最终可能会遇到不同的事务,这些事务会弄乱彼此的用户变量。将查询包装在
START TRANSACTION; .... COMMIT;
中可以解决问题吗?
现在,我的查询的高级视图是:
const mysql2 = require('mysql2');
const pool = mysql2.createPool({
multipleStatements: 'true',
// other options...
}).promise();
[rows, fields] = await pool.query(`
// Clear variables, in case no result in found in following SELECT:
SET @enable=NULL, @status=NULL, ...;
// Check credentials, status, others:
SELECT blah_blah INTO @enable FROM ...
SELECT more_blah INTO @status FROM ...
//Do stuff based on these variables
SELECT some_stuff FROM somewhere WHERE @enable IS NOT NULL;
INSERT INTO someplace ... // conditioned on @status and others
`);
谢谢!
更好的做法是获取一个连接,并在您 运行 多个语句时保持该连接。这里的答案中有一个完整的示例:
该示例显示了将连接用于具有多个查询的事务,但它也应该可以将该连接用于不属于同一事务的多个语句。或者换句话说,多个事务可以在同一个连接上 运行 在该连接被释放回池之前。
当一个线程持有连接并将其用于连续查询 and/or 事务时,池不会与其他线程共享它。我不是 node.js 开发人员,所以我不知道 node.js 实现的第一手信息,但这是连接池的唯一合理实现。
此外,用户变量和其他会话状态不会泄露给其他线程。当连接返回到池中时,所有会话状态都将被擦除。为了安全起见,这也是连接池实现中应该默认的最佳实践。您不希望将您的银行路由号码存储在用户变量或临时文件中 table,然后发现下一个用户可以读取它,因为他们有机会从池中获取相同的连接。
P.S.: 我从来没有发现任何需要 multipleStatements 选项的案例,MySQL 的前工程总监告诉我:“没有正当理由使用 multi -查询作为一个特征存在。