У меня есть приложение, управляемое PHP / 5.2, которое использует транзакции в MySQL / 5.1, поэтому оно может откатить несколько вставок, если возникнет ошибка. У меня есть разные многоразовые функции для вставки разных типов элементов. Пока все хорошо.
Теперь мне нужно использовать блокировку таблицы для некоторых вставок. Как предлагается в официальном руководстве, я использую SET autocommit = 0
вместо START TRANSACTION
, поэтому LOCK TABLES
не вызывает неявной фиксации. И, как описано в документации, разблокировка таблиц неявно фиксирует любую активную транзакцию:
И здесь лежит проблема: если я просто избегаю UNLOCK TABLES
, то второй вызов LOCK TABLES
фиксирует ожидающие изменения!
Похоже, что единственный способ - выполнить все необходимые LOCK ТАБЛИЦЫ
одним оператором. Это кошмар обслуживания.
Есть ли у этой проблемы разумное решение?
Вот небольшой тестовый сценарий:
DROP TABLE IF EXISTS test;
CREATE TABLE test (
test_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
random_number INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (test_id)
)
COLLATE='utf8_spanish_ci'
ENGINE=InnoDB;
-- No table locking: everything's fine
START TRANSACTION;
INSERT INTO test (random_number) VALUES (ROUND(10000* RAND()));
SELECT * FROM TEST ORDER BY test_id;
ROLLBACK;
SELECT * FROM TEST ORDER BY test_id;
-- Table locking: everything's fine if I avoid START TRANSACTION
SET autocommit=0;
INSERT INTO test (random_number) VALUES (ROUND(10000* RAND()));
SELECT * FROM TEST ORDER BY test_id;
ROLLBACK;
SELECT * FROM TEST ORDER BY test_id;
SET autocommit=1;
-- Table locking: I cannot nest LOCK/UNLOCK blocks
SET autocommit=0;
LOCK TABLES test WRITE;
INSERT INTO test (random_number) VALUES (ROUND(10000* RAND()));
SELECT * FROM TEST ORDER BY test_id;
ROLLBACK;
UNLOCK TABLES; -- Implicit commit
SELECT * FROM TEST ORDER BY test_id;
SET autocommit=1;
-- Table locking: I cannot chain LOCK calls ether
SET autocommit=0;
LOCK TABLES test WRITE;
INSERT INTO test (random_number) VALUES (ROUND(10000* RAND()));
SELECT * FROM TEST ORDER BY test_id;
-- UNLOCK TABLES;
LOCK TABLES test WRITE; -- Implicit commit
INSERT INTO test (random_number) VALUES (ROUND(10000* RAND()));
SELECT * FROM TEST ORDER BY test_id;
-- UNLOCK TABLES;
ROLLBACK;
SELECT * FROM TEST ORDER BY test_id;
SET autocommit=1;