假设存在一个包含something
列的表id, foo, bar, baz, qux, norf, updated_at
,并且有人希望测试在此表上工作的并发事务时可能发生的各种用例,例如:
用例:如果您检查以下交易 T1 和 T2 ,例如如何测试从哪个事务隔离级别插入 T2 将在 T1中的第一个和第二个SELECT之间进行COMMIT
,那么> T2 将在第二个SELECT中可用所以我在这里测试phantom read
的一些变体我猜,虽然SELECT语句不同?
我唯一的想法是在两个SELECT语句之间使用SELECT PG_SLEEP(N);
并打开两个数据库连接(例如某个数据库客户端的2个实例,例如PgAdmin),以处理 T1 和一个处理 T2 而不是手动启动 T1 让第一个SELECT完成PG_SLEEP(10)
将触发的地方,而不是手动启动 T2 , 并希望从 T1 中查看结果并手动进行比较。但似乎这是不可能的,因为我没有找到任何可以从2 + SELECT语句返回多个结果集的DB客户端。
(顺便说一下,使用一个SELECT而不是两个SELECT会很棒,不知怎的合并到一个SELECT但是我没有看到怎么做的方式)
T1:
START TRANSACTION;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
...
SELECT sum(foo) as foo
FROM something
WHERE bar = 1 AND updated_at <= '...' AND norf = 2
UNION ALL
SELECT sum(foo)
FROM something
WHERE bar = 1 AND baz IN (1, 9, 10) AND updated_at > '...'
GROUP BY bar;
SELECT PG_SLEEP(10);
SELECT bar, qux, sum(foo) AS foo
FROM something
WHERE norf = 2
GROUP BY bar, qux;
COMMIT;
T2:
START TRANSACTION;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
...
INSERT INTO something VALUES(...);
...
COMMIT;
请不要发布答案,例如“READ COMMITTED是postgre的默认事务级别,你不需要指定它”我只是作为一个例子使用它,或者“你将通过使用REPEATABLE READ来解决问题postgre“因为我想从测试中得到答案。
虽然我在少数几个地方提到了postgre,我正在使用mysql
和sql-server
,因为问题与它们都没有关系。
我也检查过已提出的问题:
How to test MySQL transactions?
How to test concurrency locally?
答案 0 :(得分:3)
对于Sql Server,我通过在Sql Server Management Studio中打开两个不同的窗口来测试这种类型的场景。每个窗口都有自己与数据库的连接。然后,我逐步执行T1和T2的相关部分,以重现所需的测试用例。
我确信你可以使用各自的工具与其他数据库做一些非常相似的事情。
示例:
窗口1
START TRANSACTION;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
...
SELECT sum(foo) as foo
FROM something
WHERE bar = 1 AND updated_at <= '...' AND norf = 2
UNION ALL
SELECT sum(foo)
FROM something
WHERE bar = 1 AND baz IN (1, 9, 10) AND updated_at > '...'
GROUP BY bar;
窗口2
START TRANSACTION;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
...
INSERT INTO something VALUES(...);
...
COMMIT;
窗口1
SELECT bar, qux, sum(foo) AS foo
FROM something
WHERE norf = 2
GROUP BY bar, qux;
COMMIT;