【问题标题】:PHP Incrementing Max IDPHP递增最大ID
【发布时间】:2015-11-17 09:30:49
【问题描述】:

您好,我有一个代码可以检查username 是否存在,如果存在,我想将变量$var 设置为现有username 的当前accountID。如果username 不存在,我希望最新accountIDMAX 增加。这是我的代码:

$checkUname = $conn->prepare("SELECT accountID from accounts WHERE username=?");
$checkUname->execute(array($_POST['txt_un']));
$row = $checkUname->fetch(PDO::FETCH_ASSOC);
if($row > 0) {
    $var = $row['accountID'];
} else {
    $getMax = $conn->query("SELECT MAX(accountID) as maxAccountID FROM accounts");
        $row = $getMax->fetch(PDO::FETCH_ASSOC);
            $maxID = $row['maxAccountID'];
            $maxID++;

        $var = $maxID;
}

$UpdateTable = $conn->prepare("UPDATE otherTable SET someField=? WHERE otherTableID=?");
$UpdateTable->execute(array($var, $_POST['tableID']));

现在我的问题是,如果 2 个或更多用户同时点击并运行上面的代码怎么办? incrementing ID 会不会有问题?

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    您可以使用此查询一次获取数据

    IF EXISTS (SELECT accountID from accounts WHERE username=?) THEN
        SELECT accountID from accounts WHERE username=?;
      ELSE 
        SELECT MAX(accountID) as maxAccountID FROM accounts;
      END IF;
    

    【讨论】:

      【解决方案2】:

      这就是为什么您应该将 accountID 设置为自动增量列 https://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html

      然后您可以使用 LAST_INSERT_ID() 来获取插入用户的 id。上面的页面有这个功能的链接。

      PHP 有特定的函数使用 LAST_INSERT_ID(),每个库都有其特定的函数:

      【讨论】:

      • 为什么要链接已弃用的函数?
      • @CharlotteDunois 因为我不想限制答案。如果有人出于任何原因使用旧库、旧方法、版本或其他任何东西,他也有权获得信息。此外,根据 PHP 版本,页面上有信息表明它已被弃用/删除,这也是相关且重要的。
      【解决方案3】:

      以下是此链接的部分摘录:click me

      它并不完全是您所需要的,但它有处理此类问题的方法。它暗示你正在使用 MySQL InnoDB。如果您使用 MyISAM 或 MariadDB,解决方案可能会有所不同。

      摘录:

      让我们看另一个例子:我们在表 child_codes 中有一个整数计数器字段,我们使用它为添加到表 child 的每个子项分配一个唯一标识符。使用一致读取或共享模式读取来读取计数器的当前值不是一个好主意,因为数据库的两个用户可能会看到相同的计数器值,并且如果两个用户会出现重复键错误尝试将具有相同标识符的子代添加到表中。

      在这种情况下,有两种很好的方法来实现计数器的读取和递增:

      First update the counter by incrementing it by 1, and then read it.
      
      First perform a locking read of the counter using FOR UPDATE, and then increment the counter.
      

      后一种方法可以实现如下:

      SELECT counter_field FROM child_codes FOR UPDATE;
      UPDATE child_codes SET counter_field = counter_field + 1;
      

      A SELECT ... FOR UPDATE 读取最新的可用数据,在它读取的每一行上设置排他锁。因此,它设置的锁与搜索的 SQL UPDATE 在行上设置的锁相同。

      前面的描述只是 SELECT ... FOR UPDATE 工作原理的一个例子。在 MySQL 中,生成唯一标识符的具体任务实际上只需要对表进行一次访问即可完成:

      UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
      SELECT LAST_INSERT_ID();
      

      SELECT 语句仅检索标识符信息(特定于当前连接)。它不访问任何表。

      【讨论】:

        【解决方案4】:

        一般没问题。为什么?

        这取决于很多因素,从数据库执行此类查询的能力、服务器处理、互联网连接等开始......

        通过下面的链接获取真实和具体的信息

        How many MySql queries/second can be handled by a server?

        http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html

        重要:

        什么是 PDO?

        PHP 数据对象或 PDO 是专门用于 PHP 应用程序的数据库抽象层。 PDO 为您的 PHP 应用程序提供一致的 API,无论您的应用程序将连接到哪种类型的数据库服务器。理论上,如果您使用 PDO API,您可以将您使用的数据库服务器从 Firebird 切换到 MySQL,并且只需要对您的 PHP 代码进行微小的更改。

        数据库抽象层的其他示例包括用于 Java 应用程序的 JDBC 和用于 Perl 的 DBI。

        虽然 PDO 有其优点,例如干净、简单、可移植的 API,但它的主要缺点是它不允许您使用最新版本中可用的所有高级功能MySQL 服务器的版本。 例如,PDO 不允许您使用 MySQL 对多语句的支持。

        http://php.net/manual/en/mysqli.overview.php

        【讨论】:

          猜你喜欢
          • 2015-07-05
          • 1970-01-01
          • 1970-01-01
          • 2016-01-04
          • 1970-01-01
          • 1970-01-01
          • 2017-08-01
          • 2013-12-22
          • 1970-01-01
          相关资源
          最近更新 更多