简体   繁体   English

mysql 连接池、并发事务和@用户变量

[英]mysql connection pool, concurrent transactions and @ user variables

I am trying to figure out if I have a problem with how I use a mySql db in an application.我想弄清楚在应用程序中如何使用 mySql 数据库是否有问题。 I am running nodejs, express, mysql2, and use connection pooling, with multiple statements queries.我正在运行 nodejs、express、mysql2,并使用连接池,以及多个语句查询。 I have multiple servers, running different services, accessing the same db.我有多个服务器,运行不同的服务,访问同一个数据库。

At the beginning of each mySql instructions set, I set some user variables to check user credentials, latest status etc... In following instructions, I use these variables to conditionally access some data, or also do inserts, modify data.在每个 mySql 指令集的开头,我设置了一些用户变量来检查用户凭据、最新状态等......在下面的说明中,我使用这些变量有条件地访问一些数据,或者也做插入、修改数据。 There are different players involved here (nodejs, mysql2 driver, mysql specs, innoDb engine), and I am not sure on which has the definite answer to the following:这里涉及到不同的参与者(nodejs、mysql2 驱动程序、mysql 规格、innoDb 引擎),我不确定哪个对以下问题有明确的答案:

  • Are all my instructions in my multiple statements query going to be run in one shot, or do I need to worry about different instructions from different queries and/or servers interleaving?我的多个语句查询中的所有指令是否将一次性运行,还是我需要担心来自不同查询和/或服务器交错的不同指令?
  • user variables are maintained per connection.每个连接都维护用户变量。 If instructions can interleave, I could end up with different transactions messing up each other's user variables.如果指令可以交错,我最终可能会以不同的事务混淆彼此的用户变量。 Would wrapping a query in a START TRANSACTION; .... COMMIT;将查询包装在START TRANSACTION; .... COMMIT; START TRANSACTION; .... COMMIT; fix the problem?解决问题?

Right now, a high level view of my queries would be:现在,我的查询的高级视图将是:

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
`);

Thanks!谢谢!

The better practice is to acquire a connection, and hold onto that connection while you run multiple statements.更好的做法是获取一个连接,并在运行多个语句时保持该连接。 There's a complete example in an answer here: node.js mysql pool beginTransaction & connection这里有一个完整的答案示例: node.js mysql pool beginTransaction & connection

The example shows using a connection for a transaction with multiple queries, but it should also work to use that connection for multiple statements that are not part of the same transaction.该示例显示了将连接用于具有多个查询的事务,但也应该将该连接用于不属于同一事务的多个语句。 Or stated another way, multiple transactions can be run on the same connection before that connection is released back to the pool.或者换一种说法,在该连接被释放回池之前,可以在同一个连接上运行多个事务。

While one thread holds a connection and uses it for successive queries and/or transactions, the pool will not share it with other threads.虽然一个线程持有一个连接并将其用于连续查询和/或事务,但池不会与其他线程共享它。 I'm not a node.js developer so I don't know this first-hand about the node.js implementation, but that's the only sensible implementation of a connection pool.我不是 node.js 开发人员,所以我不了解 node.js 实现的第一手资料,但这是连接池的唯一合理实现。

Also, user variables and other session state is not leaked to other threads.此外,用户变量和其他 session state 不会泄露给其他线程。 When a connection is returned to the pool, all session state is wiped.当连接返回到池时,所有 session state 都会被擦除。 That's also a best practice that should be default in the connection pool implementation, for security.为了安全起见,这也是连接池实现中默认的最佳实践。 You wouldn't want your bank routing number to be stored in a user variable or a temp table, and then find that the next user could read it because they chanced to acquire the same connection from the pool.您不希望您的银行路由号码存储在用户变量或临时表中,然后发现下一个用户可以读取它,因为他们有机会从池中获取相同的连接。

PS: I've never found any case that required the multipleStatements option, and it was told to be by the former Engineering Director of MySQL: "there's no legitimate reason for multi-query to exist as a feature." PS:我从来没有发现任何需要multipleStatements选项的案例,MySQL的前工程总监告诉我:“没有正当理由将多查询作为一项功能存在。”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM