这个缓存是如何使用的
CakePHP 中对 method_cache 的唯一引用是在 Dbo Source 中。这是一个在该类中广泛使用的缓存,用于缓存(relatively) expensive quoting operations 的结果,或者如a relevant docblock 所示:
缓存来自查询解析操作的结果。 DboSource::name() 和 DboSource::conditions() 的缓存结果都将存储在这里。
考虑以下外壳:
<?php
class SoShell extends AppShell {
function main() {
$this->Post = ClassRegistry::init('Post');
$this->Post->find('all', array(
'conditions' => array(
'find-this-text' => 'x'
)
));
debug(DboSource::$methodCache);
}
}
运行它,产生以下输出:
> Console/cake so
########## DEBUG ##########
array(
'name' => array(
'f5442d1f57be5d9d8ac80ae9613d5ff9' => '`database_name`',
'cfacfed443d6f30e67edf9bbcb06ce30' => '`posts`',
'e13d78515036382daf55fa083088c902' => '`Post`.`id`',
'aafd056e6d53878a75ab4ee3f18645a1' => '`Post`.`title`',
'4084e974416e3a7fb06e6a280721637b' => '`Post`.`body`',
'b4f1ad1de4cdc3a3f82e905f8dfd8673' => '`Post`.`created`',
'bfeffce70e344d7606e17c9ff24530b5' => '`Post`.`modified`',
'e42609d9744a7d1ce80c8d838b9ea07c' => '`find-this-text`', # <-
'c0a33fa0f04ac4682dcdc4b25167b3a8' => '`Post`'
),
'fields' => array(
'952d56c2bf037c8195bdd5fba57b1024' => array(
(int) 0 => '`Post`.`id`',
(int) 1 => '`Post`.`title`',
(int) 2 => '`Post`.`body`',
(int) 3 => '`Post`.`created`',
(int) 4 => '`Post`.`modified`'
)
)
)
请注意,缓存包含“用户”(或开发人员)输入,该数组是写入缓存 at the end of a request 的内容。
这个例子还应该强调为什么缓存会随着时间增长 - 缓存依赖于迄今为止发出的查询,随着时间的推移,更多的查询排列由应用程序发出,导致方法缓存增长(但通常不会很多MB)。
轻松修复
对所描述的问题有一个非常简单的解决方法:禁用方法缓存。
即将以下内容放在您的应用程序中的任何位置:
DboSource::$cacheMethods = false;
这当然意味着性能下降,因为不会使用方法缓存,因此每个请求都会发生相对昂贵的基于 preg 的引用操作。
更好的修复
如果缓存被“模型的 db-instances”填充 - 很可能某处存在应用程序问题。这是不正常的,它不应该发生,并且完全取决于应用程序正在做什么。鉴于无法给出具体的解决方案。
但是,如果您可以识别缓存中包含大量数据的任何特定键,则可以使用它来查找负责的查询。例如:
// anywhere
if (isset(DboSource::$methodCache['name']['e42609d9744a7d1ce80c8d838b9ea07c']) {
// a query with find-this-text has been issued somewhere
}
您可以(临时)将这种逻辑添加到where the dbo methodCache property is modified 以便能够“原位”检测修改:
public function cacheMethod($method, $key, $value = null) {
if ($this->cacheMethods === false) {
return $value;
}
if (!$this->_methodCacheChange && empty(self::$methodCache)) {
self::$methodCache = Cache::read('method_cache', '_cake_core_');
}
if ($value === null) {
return (isset(self::$methodCache[$method][$key])) ? self::$methodCache[$method][$key] : null;
}
$this->_methodCacheChange = true;
// Added
if ($method === 'name' && $key === 'e42609d9744a7d1ce80c8d838b9ea07c') {
App::uses('Debugger', 'Utility');
$this->log("Query with find-this-text in it issued", "wat-debug");
$this->log(Debugger::trace(), "wat-debug");
}
// Added end
return self::$methodCache[$method][$key] = $value;
}
这将允许您确定直接负责将大量数据注入方法缓存的原因;然后更正应用程序代码,以便可以按设计启用和使用方法缓存。