我有一个人制作的这个剧本,我查看了它并发现了一些我不确定是安全的:
在一个事务中,在2个不同的表中有2个连续插入,两个表都有自动递增的主键。它们应该是相同的(从第一个插入生成的主键=从第二个插入生成的主键)。
不要问我为什么,这就是脚本是如何制作的。
我是新手,我无法弄清楚这里是否存在并发问题。我正在考虑另一个线程在同一时间运行的可能性,最后生成的键如下:
Thread #1: Table_A ID: 3 Table_B ID: 4
Thread #2: Table_A ID: 4 Table_B ID: 3
我很确定(我今天第一次只准备好与事务相关的文档)交易无法防范这种情况,但我只是想确保我做对了。
谢谢!
答案 0 :(得分:1)
您需要将两个连接放在可序列化的事务隔离级别中,以避免您描述的场景,方法是在每个连接上设置tx_isolation
:
SET @@tx_isolation = SERIALIZABLE;
或
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
或通过以下方式设置全局隔离级别:
SET @@global.tx_isolation = SERIALIZABLE;
或
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
由任何后续打开的连接继承。在该级别,如果另一个事务正在进行中,事务将阻止任何查询,即。事务已经在相同的表上发出了查询(读或写)。
有关详细信息,请参阅the mysql documentation。
答案 1 :(得分:0)
您的情况绝对可能。
如果两个表中的主键应该相同,则可以覆盖第二个表中的AUTO_INCREMENT
并显式插入值:
INSERT
INTO a (id)
VALUES (NULL) -- this inserts an auto incremented value
INSERT
INTO b (id)
SELECT LAST_INSERT_ID() -- this inserts the last value inserted into a in this session