【问题标题】:How can I get the primary key of an updated row in mysql?如何获取mysql中更新行的主键?
【发布时间】:2015-04-08 07:56:15
【问题描述】:

在有两个表usersapples 的数据库中,我想将一个苹果分配给一个用户,然后知道苹果ID。可以将多个苹果分配给一个用户。我在 PHP 中工作。

// users asks for an apple - lets find a vacant one
$apple_id = $dbh->query("SELECT id FROM apple WHERE user_id IS NULL LIMIT 1")->fetchColumn();

// hope fully we found an apple, lets assign it
$sth = $dbh->prepare("UPDATE apple SET user_id = ? WHERE apple_id = ?");
$sth->execute(array($user_id,apple_id));

问题是另一个事务可以选择同一个苹果,然后一个用户会覆盖另一个用户的苹果。 如果我在更新语句中包含AND user_id IS NULL,我将冒着得不到苹果的风险。

我知道我可以选择UPDATE apple SET user_id = ? WHERE user_id IS NULL,但之后我就不知道苹果ID了。

有没有办法获取更新行的主键? 像lastUpdatedId 这样的东西会很好。

但我认为我必须使用事务。但是我必须选择哪个隔离级别?可重复阅读?可序列化?为什么?这意味着什么?它会只锁定行还是整个表?

【问题讨论】:

    标签: php mysql sql pdo transactions


    【解决方案1】:

    您可以执行以下操作:

    update apple
        set user_id = if(@apple_id := apple_id, ?, ?)
        where user_id is null
        limit 1;
    
    select @apple_id;
    

    【讨论】:

    • 是的,看起来不错!但是,我刚刚找到了FOR UPDATE 选择模式,这似乎正是我想要的
    • @Surrican 。 . .请小心使用for update。应用程序的来回在数据库时间上非常耗时,这导致锁被持有更长的时间(更不用说如果您正在等待用户输入或有一些有趣的事情可能发生)其他错误)。
    • 你能解释一下你的解决方案吗?我是否正确假设您只是使用 if 语句将当前行中的 id 分配给可用,并且两个 ? 占位符都持有相同的值(user_id)?所以 if 语句实际上只是“误用”来执行变量赋值? @戈登林诺夫
    • 实际上赋值应该返回 true,所以 if(@apple_id := apple_id, ?, null) 应该没问题?
    【解决方案2】:

    SELECT ... FOR UPDATE 将产生完全期望的效果:

    http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

    $dbh->beginTransaction();
    
    // users asks for an apple - lets find a vacant one
    $apple_id = $dbh->query("SELECT id FROM apple WHERE user_id IS NULL LIMIT 1 FOR UPDATE")->fetchColumn();
    
    // hope fully we found an apple, lets assign it
    $sth = $dbh->prepare("UPDATE apple SET user_id = ? WHERE apple_id = ?");
    $sth->execute(array($user_id,apple_id));
    
    $dbh->commit();
    

    第二个事务将等到第一个事务提交。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 1970-01-01
      • 1970-01-01
      • 2015-06-21
      • 2010-11-26
      • 1970-01-01
      相关资源
      最近更新 更多