MySQL nodejs 中的隔离级别。连接中的每个查询是独立的还是每个池都是独立的?
MySQL isolation levels in nodejs. Is each query in connection isolated or each pool isolated?
我当前 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
Every method you invoke on a connection is queued and executed in
sequence.
我不太确定那是什么意思。
此外,如果我使用连接池,我能否 100% 确定并发的 运行ning 查询由不同的会话处理?因此,例如,如果在第一个查询中未释放池,那么第二个查询是否总是由另一个会话执行?
我做了一些测试,发现 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
表示第一个事务正在阻止第二个事务的执行。
所以当文档说
Every method you invoke on a connection is queued and executed in sequence
意味着它们是顺序传递到数据库的,但即使在事务下它仍然是异步和并行的。但是,连接池会导致多个连接的实例化,并且不同池连接内的事务对每个事务的行为都符合预期。
我当前 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
Every method you invoke on a connection is queued and executed in sequence.
我不太确定那是什么意思。
此外,如果我使用连接池,我能否 100% 确定并发的 运行ning 查询由不同的会话处理?因此,例如,如果在第一个查询中未释放池,那么第二个查询是否总是由另一个会话执行?
我做了一些测试,发现 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
表示第一个事务正在阻止第二个事务的执行。
所以当文档说
Every method you invoke on a connection is queued and executed in sequence
意味着它们是顺序传递到数据库的,但即使在事务下它仍然是异步和并行的。但是,连接池会导致多个连接的实例化,并且不同池连接内的事务对每个事务的行为都符合预期。