【问题标题】:PDO + PHP lastInsertId() issuePDO + PHP lastInsertId() 问题
【发布时间】:2012-07-09 20:21:32
【问题描述】:

如果例如当用户单击链接时,会自动插入新行,然后php代码请求最后插入的id,同时插入另一行另一个用户,所以返回的 id 实际上不是我期望的那个..?

我错了吗?有没有办法在没有“安全”漏洞的情况下做同样的事情?
(比如可能来自准备好的声明或其他东西......)

P.S id 是自动生成的。

谢谢。

【问题讨论】:

    标签: php mysql database pdo lastinsertid


    【解决方案1】:

    manual中提到的:

    LAST_INSERT_ID()(不带参数)返回一个 BIGINT(64 位)值,该值表示 第一个自动生成的值,该值由 most 为 AUTO_INCREMENT 列设置最近执行了 INSERT 语句来影响这样的列。例如,插入一行生成AUTO_INCREMENT值的行后,可以得到这样的值:

    mysql>SELECT LAST_INSERT_ID();
        ->195
    

    当前执行的语句不影响 LAST_INSERT_ID()。假设您生成一个AUTO_INCREMENT 值 用一个语句,然后参考LAST_INSERT_ID() 多行INSERT 将行插入到表中的语句 拥有AUTO_INCREMENT 列。 LAST_INSERT_ID() 的值将保持不变 在第二个语句中稳定;第二次及以后的价值 rows 不受早期行插入的影响。 (但是,如果你 混合对LAST_INSERT_ID()LAST_INSERT_ID(expr) 的引用,即 效果未定义。)

    如果前面的语句返回错误,则值为 LAST_INSERT_ID() 未定义。对于事务表,如果 语句由于错误而回滚,值为 LAST_INSERT_ID() 未定义。对于手动回滚,值 LAST_INSERT_ID() 没有恢复到交易前的状态;它 保持在ROLLBACK 的位置。

    所以,LAST_INSERT_ID() 始终是事务安全的(即使您不使用事务)。

    【讨论】:

    • lastInsertId() 由 PDO 驱动程序本身提供,可能是也可能不是对 SELECT LAST_INSERT_ID(); 的实际 SQL 查询。虽然这可能仍然完全正确,但仅基于此还不能确定!
    【解决方案2】:

    在成功INSERT 后,MySQL 服务器将插入 ID 作为OK 消息的一部分传输。此 ID 存储在 PDO 中,因此无需往返服务器 PDO 就可以安全地为您的连接返回正确的 ID。

    参考:http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#OK_Packet

    【讨论】:

      【解决方案3】:

      为了解决这个问题,您可以使用transaction

      这基本上会将您的插入与其他插入隔离开,因此只要您的 Insert/lastInsertId() 调用在同一个事务中,它就可以正常工作。

      【讨论】:

      • 所以应该是这样的吧? : 1) $dbh->beginTransaction(); 2) 插入代码 + lastInsertId() 3) $dbh->commit();
      • @xTCx 完全正确;如果您在交易中所做的事情有问题,您也可以rollback :)
      • 如果不是完全不正确,这个答案会产生误导。 lastInsertId() 的底层功能是连接感知的。因此它将返回调用它的连接最后插入的 ID。如需更好的答案,请查看this one
      • @Adnan 他们也有交易意识,这让我的回答完全有效。如果您仍然不同意,我建议您阅读交易。
      • @RudiVisser A- 我同意你的评论。 B-OP 没有提到交易。建议人们实施交易以解决不存在的问题是荒谬的。虽然您确实提供了一般有用的建议,但您的回答在这个问题的背景下是没有帮助的。
      猜你喜欢
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 2021-12-27
      • 2020-01-01
      • 2020-10-30
      相关资源
      最近更新 更多