代码之家  ›  专栏  ›  技术社区  ›  Attila Kun

我应该如何在PHP中处理查询同步?

  •  3
  • Attila Kun  · 技术社区  · 15 年前

    我想在一个表中插入一些值,它有一个自动递增的字段作为主键。然后我想用 mysql_insert_id() 并将此ID用作另一个表中的外键。问题是,尽管可能性很小,但在第一次插入和随后的检索之间,可能会有另一次插入发生在第一个表中,因此会返回一个错误的ID。

    PHP是自动处理的,还是我的关注点有效?如果是这样,我怎样才能克服它们?

    3 回复  |  直到 15 年前
        1
  •  4
  •   Decent Dabbler    15 年前

    mysql_insert_id()将返回每个连接基上最后一个插入的id。所以基本上,如果这是您的担心,那么您不必担心并发脚本请求。

    供参考: see the MySQL docs .

    编辑:

    顺便说一句,你可以很容易地测试这个。

    测试程序

    <?php
    
        $sleep = isset( $_GET[ 'sleep' ] ) ? true : false;
    
        $conn = mysql_connect( /* your parameters */ );
        mysql_select_db( /* your db */, $conn );
    
        $sql = 'INSERT INTO yourtable(id,col1,col2) VALUES(null,"test","test")';
        mysql_query( $sql );
    
        if( $sleep ) sleep( 5 );
    
        echo mysql_insert_id();
    ?>
    

    打开两个浏览器选项卡:

    第一个请求:
    http://localhost/test.php?sleep=1

    在第二秒内请求,例如,最多4秒:
    http://localhost/test.php

    第一个请求应该给您一个小于第二个请求的ID。

        2
  •  3
  •   code_burgar    15 年前

    SQL transactions 是你需要的。在MySQL中,InnoDB是唯一支持事务的引擎。

        3
  •  -2
  •   ftrotter mario    15 年前

    您可以使用两种一般策略来确保此问题不会影响您。首先,您可以使用事务(如另一位作者指出的那样)。

    但是从性能角度来看,手动跟踪ID号可能更快。您可以通过使用数据库中的全局ID来实现这一点。使系统中的ID全局唯一的滚动编号。

    假设全局ID是100,您知道您需要6个ID。然后在全局ID表的全局ID行中写出106…然后使用101作为第一个条目,这是102数据点中的外键,依此类推。这大大提高了处理大型数据集时的性能。

    因此,如果您需要制作100个新的插入,这可能是一个好主意。如果你一次只需要6个……使用事务…

    正如jmucchiello在评论中所建议的。您可以使用UPDATE语句来确保另一个进程没有写入全局ID条目。类似的东西

    更新globaltable set id=106,其中id=100

    我可以看到我正在修改这个答案,但是如果你有一百万行要导入,这确实是最好的策略…哦,好吧……

    -FT