Php 使用$GLOBAL防止在选择最新ID+1和插入之间出现重复密钥问题

Php 使用$GLOBAL防止在选择最新ID+1和插入之间出现重复密钥问题,php,mysql,Php,Mysql,这是一个12年前用PHP5.3编写的脚本,我最近升级到了5.6 它与paypal parallel payments(paypal并行支付)的接口源自于年,但不确定它是如何存活这么长时间的缺陷是: 用户A进入付款页面 生成$order\u id:mysql\u queryselect maxorder\u id+1作为orders的id; $order\u id被插入到其他两个表中 用户A被重定向到Paypal 同时 用户B进入付款页面。 $order\u id相同,因为orders表尚未更新

这是一个12年前用PHP5.3编写的脚本,我最近升级到了5.6

它与paypal parallel payments(paypal并行支付)的接口源自于年,但不确定它是如何存活这么长时间的缺陷是:

用户A进入付款页面 生成$order\u id:mysql\u queryselect maxorder\u id+1作为orders的id; $order\u id被插入到其他两个表中 用户A被重定向到Paypal 同时

用户B进入付款页面。 $order\u id相同,因为orders表尚未更新 因此,现在无论哪个用户通过paypal SECOND订购并将成功返回到支付脚本,INSERT语句都将失败,因为$order\u id已经插入到表中

我们将在一两个月内更换整个系统,需要快速修复

我的第一个想法是:

//source: https://stackoverflow.com/a/3146986/2223106
define('MYSQL_CODE_DUPLICATE_KEY', 1062);
mysql_query($sql);
if (mysql_errno() == MYSQL_CODE_DUPLICATE_KEY) {
    $Invoice_id++;
    $sql = "INSERT etc
但是现在我意识到也许我可以定义一个全局$order\u id并对照mysql\u query检查它从orders中选择maxorder\u id+1作为id;,然后,如果它与当前下一个id匹配,则将其递增1

这似乎是一种合理的方法:

$excqry=mysql_query("select max(order_id)+ 1 as id from orders ") or die(mysql_error());

if(mysql_num_rows($excqry) > 0) {

  $row1=mysql_fetch_array($excqry);

  $Invoice_id = $row1['id'];

  if (isset($GLOBALS['order_id']) && ($GLOBALS['order_id'] <= $Invoice_id)){
    $GLOBALS['order_id'] = $Invoice_id + 1;
    $Invoice_id++;
  }

  // Continue with our MySQL statements

显然,这并不能解决用户C可能同时出现的问题,但该网站每周只有几十个用户。

$MikeiLL我还认为最好将order_id作为主要用户,这样它将自行增加,而不是跟踪,GLOBAL不是一个好主意

因此,为了解决您的问题,您应该执行以下步骤

将订单id定义为主键 添加到它的自动增量。 然后,在控制器中,在所有检查之后立即存储订单,然后使用mysql\u insert\u id检索订单id 现在,您可以在任何需要的地方插入$order\u id
似乎列上已经有一个无重复约束,您不能简单地将其设置为主键(它应该是主键)并使其自动递增吗?全局变量只是个坏主意,不会解决您的问题。为什么不在将$order\U id分配给其他表之前,对order\U id使用自动增量并将您的订单存储在DB中?只需将你的订单存储在DB中,使用类似MySqLyEndotTyl ID或它的类似物。考虑从MySQL升级到MySQL,MySQL在5。x中被弃用。X.@ Aknasi我知道,至少在这个页面上升级到myQuLi是相当基本的,并且如果代码库需要更长的时间。但这并不能解决这个问题,对吗?@MikeiLL,没错。只需将order_id定义为主键,并将其添加到AUTO_INCREMENT中即可。然后使用mysql\u insert\u id来检索order\u id,仅此而已