我目前正在尝试改进我们应用程序的测试行为。
测试当前在嵌套事务中启动,其中测试套件启动实际事务,并且每个测试用例都创建嵌套保存点。
当一个测试用例完成时,保存点被简单地释放并恢复原始数据。套件完成后,事务将回滚。
(在表上使用截断对我们来说不是一个选项,因为种子数据太大而且它会阻止中央和并发测试)
这工作正常。
当事务并发运行时,事务倾向于将彼此锁定在表之外。这种情况在具有唯一键的表上更是如此(两个事务之一的每个测试都失败)。
我尝试使用事务状态“READ COMMITTED”、“READ UNCOMMITED”和默认的“REPEATABLE READ”来执行此操作。
READ UNCOMMITTED 导致重复的关键问题。READ COMMITTED 有锁/死锁问题 REPEATABLE READ 有锁/死锁问题(同上)
此外,我尝试应用以下选项:innodb_autoinc_lock_mode=2
> -- mysql command line
> SET SESSION binlog_format=ROW
> SET SESSION innodb_table_locks=OFF
最后一个参数解决了一些锁定问题。“锁定等待超时”和死锁问题仍然存在。
是否有解决方案使单独的交易真正相互独立?
更新:进一步的测试表明:死锁目前只发生在具有唯一键的表上。我认为会话 1 已经使用了这些键,所以我可能是行锁定的受害者。
mysql服务器版本:5.5.15
编辑:添加工作流示例,以便更清楚地说明问题(可能包含拼写错误和轻微的语法错误。这些不是重点)。不同的连接 不同的意图
> create table foo (
> `id` int(11) auto increment,
> `name` varchar(255),
> PRIMARY KEY id,
> UNIQUE KEY `name`(`name`)
> ) ENGINE=InnoDb;
> insert into foo(name) values ('bar');
> begin; -- connection 1, transaction 1
> begin; -- connection 2, transaction 1
> savepoint t_1; -- connection 1, savepoint within transaction 1
> savepoint t_1; -- connection 2, savepoint within transaction 1
> select count(*) from foo; -- connection 1, number of entries in foo, should be 1
> insert into foo('name') values ('meh'); -- connection 1, insert into foo the unique fixed value 'meh', should work
> select count(*) from foo; -- connection 2, number of entries in foo, should be 1
> insert into foo('name') values ('meh'); -- connection 2, insert into foo the unique fixed value 'meh', should work
> select count(*) from foo; -- connection 1, number of entries in foo, should be 2
> select count(*) from foo; -- connection 2, number of entries in foo, should be 2
> rollback to savepoint t_1; -- connection 1, discard everything up until savepoint t_1
> rollback; -- connection 1, rollback
> rollback to savepoint t_1; -- connection 2, discard everything up until savepoint t_1
> rollback; -- connection 2, rollback
在这个例子中,所有应该被认为是我想要的事务隔离的测试。