mysql - 在创建条目之前检查条目是否存在仍然会引发重复条目错误

标签 mysql cakephp cakephp-1.3

我有一个包含 alias 列和 item_id 列的表格。这两个字段一起创建一个唯一索引。

然后我有一些具有别名项目ID的代码,并且想要更新它的记录(或者创建一条记录,如果它不存在)

//get the current stats for this item
$stats = $model->query(
    'SELECT *, DATEDIFF(NOW(),decayed) as days_since_decay, DATEDIFF(NOW(),created) as days_active
    FROM popularity_views 
    WHERE item_id = '.$query[0][$model->alias]['id'].'
    AND alias = "'.$model->alias.'"'
);
if(empty($stats))
{
    //create new entry
    $insert = $model->query(
        'INSERT INTO popularity_views (item_id, views, alias, created, decayed) 
        VALUES ('.$query[0][$model->alias]['id'].', 1, "'.$model->alias.'", NOW(), NOW())'
    );
}

不知何故,这段代码被调用了两次,我不知道如何调用。即使它被调用两次也没关系,因为正如您所看到的,我会在添加条目之前检查以确保条目不存在。

但是,在加载此页面时(如果在加载页面之前条目不存在),它会尝试两次创建条目并抛出 SQL 错误 1062:重复条目。这对我来说没有意义。此外,如果该条目在页面加载之前就已经存在,那么它就足够聪明,根本不会尝试添加它。

有什么想法吗?

最佳答案

如果此代码在两个单独的线程中执行(例如来自两个 Web 请求),则可能存在竞争条件。也就是说,事情按以下顺序发生:

  1. 在线程 #1 中选择执行
  2. 在线程 #2 中选择执行
  3. 插入线程 #1 执行
  4. 插入线程 #2 执行(返回错误)

您可以通过将查询序列包装在 transaction 中来解决此问题。 (仅适用于 InnoDB 表类型),或使用 REPLACE INTO 而不是单独的 SELECTINSERT

就个人而言,我会使用最后一个选项 (REPLACE),因为它可能性能最佳,并降低代码复杂性,但有很多方法可以做到这一点。

关于mysql - 在创建条目之前检查条目是否存在仍然会引发重复条目错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7408143/

相关文章:

php - CakePHP - 同时更新多个表

php - 将 Cake 1.3 迁移到 Cake 2.0

MySQL选择日期范围问题

validation - 使用带有 Angular JS 的 CakePHP 表单验证

CakePHP 3 $this->模型->有条件获取?

php - 记住我与 session 超时有何不同

php - CakePHP:使用 optgroups 在选择上设置默认值

sql - 如何优化MySQL查询(分组和顺序)

MySQL 向外键添加注释

php - 打印数据库中的值,以逗号分隔(最后一个除外)