У меня есть приложение на основе PHP / 5.2, которое использует транзакции под MySQL / 5.1, поэтому оно может откатывать несколько вставок, если выполняется условие ошибки. У меня есть разные многоразовые функции для вставки разных типов предметов. Пока все хорошо.
Теперь мне нужно использовать блокировку таблицы для некоторых вставок. Как следует из официального руководства, я использую SET autocommit=0
вместо START TRANSACTION
, поэтому LOCK TABLES
не выдает неявный коммит. И, как задокументировано, разблокировка таблиц неявно фиксирует любую активную транзакцию:
И здесь кроется проблема: если я просто избегаю UNLOCK TABLES
, случается, что второй вызов LOCK TABLES
фиксирует ожидающие изменения!
Похоже, что единственный способ - выполнить все необходимые LOCK TABLES
в одном выражении. Это главный кошмар.
Есть ли у этой проблемы разумное решение?
Вот небольшой тестовый скрипт:
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;