【问题标题】:MySQL transactions and concurrent insertsMySQL 事务和并发插入
【发布时间】:2013-04-09 03:08:14
【问题描述】:

我得到了某人制作的这个脚本,我查看了它并发现了一些我不确定是否安全的东西:

在一个事务中,有 2 个连续插入,在 2 个不同的表中,都具有自动递增的主键。它们应该是相同的(第一次插入生成的主键=第二次插入生成的主键)。

别问我为什么,剧本就是这么写的。

我是交易新手,我不太清楚这里是否存在并发问题。我正在考虑另一个线程同时运行并最终生成密钥的可能性,例如:

Thread #1:    Table_A ID: 3                                        Table_B ID: 4
Thread #2:                      Table_A ID: 4     Table_B ID: 3

我很确定(我今天才第一次准备与交易相关的文档)交易无法防止这种情况发生,但我只是想确保我做对了。

谢谢!

【问题讨论】:

  • 您可以通过启动两个控制台会话来测试您的理论,并按照您认为会产生问题的顺序逐步在每个控制台中输入您的交易。您甚至可以尝试使用不同的隔离级别来做同样的事情,看看是否有任何变化。
  • 对 :) 我完全没想到。我忘记了整个控制台方法。谢谢!

标签: mysql concurrency insert transactions isolation


【解决方案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

【讨论】:

    【解决方案2】:

    你的情况绝对是可能的。

    如果两个表中的主键应该相同,您可以覆盖第二个表中的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
    

    【讨论】:

    • 是的。我知道。谢谢。我只是想确保我有真正的担心理由,因为编写脚本的人可能在整个应用程序中多次这样做:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多