几个请求同时导致错误的SQL结果

时间:2017-12-17 08:52:57

标签: php mysql nginx pdo slim

我面临一个未知问题,我创建了一个连接到Mysql的PHP API(Slim框架+ Slim PDO)。我使用Nginx作为HTTP服务器。 API使用" device-id"标头识别客户端(一个Android应用程序)。令人担忧的是,最近Android应用程序的更新使得在启动此应用程序时,如果用户未知,它现在在结果API上发出2个异步请求我发现自己在表中的两个条目用户携带相同的设备ID

在中间件

$user = new User($device_id, $ip);

在用户类

  function __construct($device_id, $ip)
  {
    $this->_device_id = $device_id;
    $this->_ip = $ip;

    if ($this->isExists())
      $this->updateInfo();
    else
      $this->createUser();
  }

  private function isExists()
  {
    global $db_core;

    $selectStatement = $db_core->select(array('id', 'current_group'))
                        ->from('users')
                        ->where('device_id', '=', $this->_device_id);
    $stmt = $selectStatement->execute();
    if ($stmt->rowCount() > 0)
    {
      $u = $stmt->fetch();
      $this->_id = $u['id'];
      $this->_current_group = $u['current_group'];
      return true;
   }
   return false;
  }

createUser()函数在users表中创建一个带有device-id的条目以及其他信息,如date等。

User lists

提前感谢您的帮助

1 个答案:

答案 0 :(得分:1)

  1. 如果表中的device_id字段应该是唯一的,则为其添加唯一索引
  2. 然后你就可以在DUPLICATE KEY上运行一个mysql查询,比如

    INSERT INTO users (...) VALUES(:device_id, :ip, ...)
    ON DUPLICATE KEY UPDATE ip = values(ip) , ...
    
  3. 我不知道是否可以使用Slim-PDO运行此类查询,但至少可以使用通用插入和更新查询,using exceptions, as shown in my article

    $this->_device_id = $device_id;
    $this->_ip = $ip;
    try {
        $this->createUser();
    } catch (PDOException $e) {
        $search = "!Integrity constraint violation: 1062 Duplicate entry\ .*? for key 'device_id'!";
        if (preg_match($search, $e->getMessage())) {
            $this->updateInfo();
        } else {
            throw $e;
        }
    }
    

    仅更新某个错误非常重要,否则重新抛出它。