Каков наилучший способ SELECT и TRUNCATE таблицы InnoDB в одной операции atomi c? - PullRequest
0 голосов
/ 09 апреля 2020

Я хочу прочитать из таблицы InnoDB, используя SELECT, а затем обрезать ее, используя TRUNCATE, за одну операцию, так что другие запросы должны ждать завершения операции TRUNCATE, прежде чем они смогут изменить таблицу. Каков наилучший способ сделать это? Насколько я понимаю, блокировки таблиц не работают с TRUNCATE. Но из моих тестов транзакции do работают с TRUNCATE. Однако транзакции гарантированно не перекрываются, если уровень изоляции SERIALIZABLE.

Я использую PHP и MySQLi. Уровень изоляции по умолчанию - REPEATABLE READ, поэтому я изменяю его на SERIALIZABLE, чтобы предотвратить одновременное изменение таблицы при запросах до завершения транзакции:

$mysqli->query("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE");

$mysqli->begin_transaction();

// Select statements reading from `my_table`

$mysqli->query("TRUNCATE `my_table`");

$mysqli->commit();

Кажется, это работает просто отлично. Мне просто интересно, есть ли лучший способ.

Ответы [ 2 ]

0 голосов
/ 16 апреля 2020

GET_LOCK() и RELEASE_LOCK() ортогональны транзакциям и т. Д. c. (Они используются крайне редко, но они могут вам понадобиться.)

0 голосов
/ 09 апреля 2020

Предполагается, что у вас включен отчет об ошибках:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

Вы можете использовать транзакции для чтения и удаления данных за один шаг. Я не уверен, почему вы установили другой режим изоляции, но я предполагаю, что он вам не нужен. Если я правильно понимаю, это заблокирует строки и предотвратит удаление.

Вы не можете использовать TRUNCATE, потому что это оператор DDL и он не работает с транзакциями. DELETE медленнее, но его можно откатить.

try {
    // Start transaction
    $mysqli->begin_transaction();

    $result = $mysqli->query('SELECT * FROM my_table');
    $mysqli->query('DELETE * FROM my_table');

    // Commit changes
    $mysqli->commit();
} catch (\Throwable $e) {
    // Something went wrong. Rollback
    $mysqli->rollback();
    throw $e;
}
...