mysql - 并发丢弃没有锁的mysql事务

标签 mysql transactions locking

我目前正在尝试改进我们应用程序的测试行为。

测试目前在嵌套事务中启动,其中测试套件启动实际事务,每个测试用例创建嵌套保存点。

当一个测试用例完成时,保存点被简单地释放并且原始数据被恢复。 套件完成后,事务将回滚。

(对表使用截断对我们来说不是一个选择,因为种子数据太大并且它阻止了集中和并发测试)

这很好用。

当事务并发运行时,事务往往会将彼此锁定在表之外。这种情况在具有唯一键的表上更是如此(两个事务之一的每个测试都失败)。

我尝试使用事务状态“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

最后一个参数解决了一些锁定问题。 “锁等待超时”和死锁问题仍然存在。

是否有解决方案使单独的事务真正相互独立?

更新:进一步测试表明: 死锁目前只发生在具有唯一键的表上。 我认为 session 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

在这个例子中,所有应该都被认为是对我想要的事务隔离的测试。

最佳答案

听起来您正试图在彼此之上同时运行测试,这就是为什么会出现并发查询的原因。如果是这样,那么我认为您 100% 正确,因为您只是遇到了锁。

如果有一个打开的事务(即长时间运行的测试),其预期目的是在测试结束时回滚,您将在进行任何其他写入时遇到很多麻烦,并且可能会在这些相同的行上进行一些读取/tables 作为其他测试的一部分。您最好的选择是按顺序运行所有内容。

您遇到的重复键问题与我在使用 READ UNCOMMITTED 时的预期一致。

关于mysql - 并发丢弃没有锁的mysql事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14485277/

相关文章:

Java EE JTA 从不事务

python - 如何在 Python 中使用计时器解锁条件?

MySQL 合并两个表

sql-server - 事务中的多个参数化的Delphi SQL更新

php - ilias LMS 的自定义报告

oracle - 如何在发出回滚前检查保存点是否已经建立?

ruby - 如何使用 fork 的 Ruby 进程进行进程间锁定?

c# - 如果我在写入变量时锁定,如果读取是原子的,我是否也需要在读取时锁定?

php - 将 PostgreSQL 连接库添加到 Azure 应用服务中

mysql - 触发器语法 mySQL