Álv*_*lez 5 mysql innodb locking transactions
我有一个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;
Run Code Online (Sandbox Code Playgroud)
显然,LOCK TABLES无法修复以很好地处理交易。解决方法是将其替换为SELECT .... FOR UPDATE。您不需要任何特殊语法(您可以使用常规START TRANSACTION)并且它按预期工作:
START TRANSACTION;
SELECT COUNT(*) FROM foo FOR UPDATE; -- Lock issued
INSERT INTO foo (foo_name) VALUES ('John');
SELECT COUNT(*) FROM bar FOR UPDATE; -- Lock issued, no side effects
ROLLBACK; -- Rollback works as expected
Run Code Online (Sandbox Code Playgroud)
请注意,这COUNT(*)只是一个示例,您通常可以使用 SELECT 语句来获取您实际需要的数据;-)
(此信息由弗兰克·海肯斯提供。)