我当前对MySQL的隔离级别是每个会话的tx_transaction = REPEATABLE-READ。
因此,当我在不同的终端中运行下面的代码时,事务是串行执行的,这意味着在提交第一个事务之前,第二个事务不会启动。
START TRANSACTION;
SELECT *
FROM test
WHERE id = 4 FOR UPDATE;
UPDATE test
SET parent = 98
WHERE id = 4;因此,如果我在nodeJS中实现了这一点,那么下面哪个结果与运行两个终端相同?
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
connection.connect();
let query =
START TRANSACTION;
SELECT *
FROM test
WHERE id = 4 FOR UPDATE;
UPDATE test
SET parent = 98
WHERE id = 4;
connection.query(query, function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
connection.query(query, function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
connection.end();或使用池
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host : 'example.org',
user : 'bob',
password : 'secret',
database : 'my_db'
});
let query =
START TRANSACTION;
SELECT *
FROM test
WHERE id = 4 FOR UPDATE;
UPDATE test
SET parent = 98
WHERE id = 4;
pool.query(query, function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
connection.release();
});
pool.query(query, function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
connection.release();
});我最初的猜测是,池将创建单独的连接,在同一个连接中发送查询将与在同一终端中键入查询相同。然而,文档中说的https://github.com/mysqljs/mysql#pooling-connections在导言部分,
在连接上调用的每个方法都按顺序排队和执行。
我不太清楚那是什么意思。
另外,如果我使用连接池,我是否可以100%地确保并发运行的查询由不同的会话处理?因此,例如,如果第一个查询中没有释放池,那么第二个查询是否总是由另一个会话执行?
发布于 2018-03-15 06:17:11
我做了一些测试,并意识到Connection Pooling的结果符合预期的结果。
当我只使用连接执行以下操作时
let pool = mysql.createConnection({
connectionLimit:10,
host: 'localhost',
user: 'root',
password: 'thflqkek12!',
database: 'donationether'
});
connection.beginTransaction(function (err) {
console.log('first transaction has started');
if (err) {
console.log(err);
return;
}
connection.query(`INSERT INTO users VALUES (null, 0, 'username', 'token')`, function (err, results, fields) {
if (err) {
console.log(err);
return;
}
setTimeout(function () {
connection.commit(function (err) {
if (err) {
console.log(err);
return;
}
console.log('first query done');
connection.release();
})
}, 2000)
});
});
connection.beginTransaction(function (err) {
console.log('second transaction has started');
if(err) {
console.log(err);
return;
}
connection.query(`UPDATE users SET username = 'c_username' WHERE username = 'username'`,function (err, results, fields) {
if(err) {
console.log(err);
return;
}
connection.commit(function (err) {
if(err) {
console.log(err);
return;
}
console.log('second query done');
connection.release();
})
});
});它会导致以下输出
first transaction has started
second transaction has started
second query done
first query done这意味着第一个连接打开的事务将被忽略,而第二个事务将在此之前完成。但是,当我将连接池用于下面的代码时,
let pool = mysql.createPool({
connectionLimit:10,
host: 'localhost',
user: 'root',
password: 'thflqkek12!',
database: 'donationether'
});
pool.getConnection(function (err, connection) {
connection.beginTransaction(function (err) {
console.log('first transaction has started');
if (err) {
console.log(err);
return;
}
connection.query(`INSERT INTO users VALUES (null, 0, 'username', 'token')`, function (err, results, fields) {
console.log('first query has started');
if (err) {
console.log(err);
return;
}
setTimeout(function () {
connection.commit(function (err) {
if (err) {
console.log(err);
return;
}
console.log('first query done');
connection.release();
});
}, 2000)
});
});
});
pool.getConnection(function (err, connection) {
connection.beginTransaction(function (err) {
console.log('second transaction has started');
if(err) {
console.log(err);
return;
}
connection.query(`UPDATE users SET username = 'c_username' WHERE username = 'username'`,function (err, results, fields) {
console.log('second query has started');
if(err) {
console.log(err);
return;
}
connection.commit(function (err) {
if(err) {
console.log(err);
return;
}
console.log('second query done');
connection.release();
})
});
});
});输出如下
first transaction has started
second transaction has started
first query has started
//2seconds delay
second query has started
first query done
second query done这意味着第一个事务正在阻止第二个事务的执行。
所以当文件上说
在连接上调用的每个方法都按顺序排队和执行。
这意味着它们是按顺序交付到数据库的,但是即使在事务处理下,它仍然是异步的和并行的。但是,连接池会导致多个连接的实例化,不同池连接中的事务按照每个事务的预期行为。
https://stackoverflow.com/questions/48969762
复制相似问题