Уровни изоляции MySQL в nodejs. Каждый запрос в соединении изолирован или каждый пул изолирован?

0

Мой текущий уровень изоляции для 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% уверенным, что одновременно выполняемые запросы обрабатываются разными сеансами? Так, например, если пул не будет выпущен в первом запросе, будет ли второй запрос ВСЕГДА выполняться другим сеансом?

Теги:
acid

1 ответ

0
Лучший ответ

Я провел несколько тестов и понял, что результаты 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

что первая транзакция блокирует выполнение второй транзакции.

Поэтому, когда в документации говорится

Каждый метод, который вы вызываете при подключении, ставится в очередь и выполняется последовательно

Это означало, что они доставляются в базу данных последовательно, но они все равно будут асинхронными и параллельными даже по транзакции. Однако объединение пулов приводит к созданию нескольких соединений, и транзакция в разных пулах ведет себя так, как ожидалось для каждой транзакции.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню