1

我正在尝试使用 Yii 框架 1.1.12 缓存从数据库中检索到的一些结果。简而言之,这是我正在做的事情:

public static function getCategories()
{
    if (self::$_categories !== null)
        return self::$_categories;

    print "Getting categories...";    
    self::$_categories = Yii::app()->cache->get("categoriesList");
    if (self::$_categories === false)
    {
        $sql = "SELECT id, parent_id, name FROM {{category}} WHERE id > 0 AND is_deleted = 0";
        $categoriesList = Yii::app()->db->createCommand($sql)->queryAll();

        // Doing some work with $categoriesList and obtaining self::$_categories as the result
        // ...

        $dependency = new CDbCacheDependency("SELECT MAX(update_time) FROM {{category}}");
        Yii::app()->cache->set("categoriesList", self::$_categories, 3600, $dependency);
    }

    return self::$_categories;
}

使用分析工具,我可以看到一切正常。第一次执行两个查询(每个查询一次):

SELECT MAX(update_time) FROM arrenda_category
SELECT id, parent_id, name FROM arrenda_category WHERE id > 0 AND is_deleted = 0

在进一步的请求中,仅执行第一个请求。

update_time问题是当我增加表中的最大值arrenda_category(即使不使用我自己的编辑脚本 - 直接从 MySQL 命令行)并刷新页面时,SELECT MAX(update_time) FROM arrenda_category查询计数变为等于 2。进一步刷新只会再次执行一次。有趣的是,如果我清除缓存,我SELECT MAX(...) ...也会执行一次查询。

所以我不明白为什么缓存依赖类的查询会在条件更改时执行两次。我的代码有问题还是有其他问题?

PS我确定SELECT MAX(update_time) FROM arrenda_category只能在上述功能中执行。我还看到print "Getting categories..."每个页面请求都会到达该行一次。

4

1 回答 1

3

是的。这是预期的。

解释

假设数据已经在缓存中。而当你调用该函数时getCategories() ,该行将Yii::app()->cache->get("categoriesList")执行依赖查询以检查数据是否更改。由于它没有改变,查询只执行一次。

现在您在外部更改了update_time值(或在您的应用程序中使用其他代码),然后getCategories()再次调用,

  1. 该行Yii::app()->cache->get("categoriesList")执行依赖查询以检查缓存中的数据是否有效。发现数据无效,返回false
  2. 然后SELECT id, parent_id, name FROM {{category}} WHERE id > 0 AND is_deleted = 0执行查询以从数据库中获取更新的数据
  3. Yii::app()->cache->set("categoriesList", self::$_categories, 3600, $dependency); AGAIN行执行相关性查询SELECT MAX(update_time) FROM {{category}}以获取最新MAX(update_time)的结果,其结果与数据一起存储。这就是查询执行两次的原因。

所以关键是每次你set()缓存一个值时,依赖值必须与它一起存储,因为后续get()查询需要它来检查依赖关系是否改变。

PS:如果您想更清楚地检查应用程序组件set()功能的源代码,它会调用类的函数,该类又调用导致执行依赖关系查询的函数cacheevaluateDependency()CDbCacheDependancygenerateDependentData()

于 2012-10-21T07:37:01.063 回答