TP模型增删改后cache查询缓存无法更新问题的解决办法
2018-03-06 22:19
344 查看
TP模型连贯操作cache方法用于select、find和getField方法,以及其衍生方法,使用cache方法后,在缓存有效期之内不会再次进行数据库查询操作,而是直接获取缓存中的数据。
第一次查询结果会被缓存,第二次查询相同的数据的时候就会直接返回缓存中的内容,而不需要再次进行数据库查询操作。
默认情况下, 缓存有效期和缓存类型是由DATA_CACHE_TIME和DATA_CACHE_TYPE配置参数决定的,但cache方法可以单独指定。
例如:
$Model->where('id=5')->cache(true)->find(); // 自动命名缓存ID,使用系统默认DATA_CACHE_TIME(0=永久有效)
$Model->cache('key',60)->find(); // 自定义缓存ID,60秒后失效
问题:
缓存有效期当然是越久越好,所以默认DATA_CACHE_TIME=0,也就是永久有效。那么问题来了,数据表增删改操作后,如何使查询缓存的数据更新呢?
用S('key',null),那不行,因为查询中用了cache(true),你根本不知道key的具体值,而且如果查询中包含了动态的where查询,那可能会产生多个缓存。
如果设置了缓存有效期cache(true,5),也就是5秒后没有命中该查询缓存的话,缓存会自动失效。这是比较简单的两头兼顾的方法,但是也有问题,在高并发情况下,缓存持续被命中,则缓存持续生效,就没有机会重新从数据表获取增删改后的新数据。对增删改后要求数据查询也立即生效的情景中,缓存刷新成了一个大问题。
综上所述,需改造一下Model类,在select(),find(),getField()方法中,有启用缓存的情况下,增加一个缓存记录逻辑。在add(), save(), delete(), setField()方法中,在有启用缓存的情况下,增加一个清理缓存的逻辑。
==================方法如下:(可作为公开方法放在Model类中,也可以作为函数放在公共函数库function.php中)===================
/**
* 清理数据表查询缓存
*
* 用于解决数据表增删改操作无法刷新查询缓存(特别是cache(true)自动命名的缓存)的问题
* 只需在增删改操作成功时,调用clear_table_caching($table);
* 即可使对应此表的所有查询缓存失效.
*
* 默认在模型的add,save,delete,setField等操作中会自动调用
*
* @param string $table 数据表名称
* @since 1.0 <2015-4-30> SoChishun Added;
*/
function clear_table_caching($table = '') {
$table_caching_keys = F('table_caching_keys');
if (!$table_caching_keys) {
return;
}
// 清理指定表的缓存
if ($table) {
if (isset($table_caching_keys[$table])) {
$values = $table_caching_keys[$table];
foreach ($values as $id) {
S($id, null);
}
unset($table_caching_keys[$table]);
F('table_caching_keys', $table_caching_keys);
}
return;
}
// 清理所有表的缓存
foreach ($table_caching_keys as $values) {
foreach ($values as $id) {
S($id, null);
}
}
F('table_caching_keys', null);
}
/**
* 添加缓存键名到数据表查询集合中
*
* 用于提供clear_table_caching()方法的数据调用
*
* 默认在getField,select,find等方法中自动调用
*
* @param string $table 数据表名称
* @param string $id 缓存键名
* @since 1.0 <2015-4-30> SoChishun Added.
*/
function log_table_cacheing($table, $id) {
$table_caching_keys = F('table_caching_keys');
if ($table_caching_keys && isset($table_caching_keys[$table]) && in_array($id, $table_caching_keys[$table])) {
return; // 如果已经存在则退出
}
$table_caching_keys[$table][] = $id;
F('table_caching_keys', $table_caching_keys);
}
============
使用方法(Model类中):
$this->log_table_cacheing($options['table'], $key); // 记录数据表的缓存键
$this->clear_table_caching($options['table']); // 清除数据表的所有查询缓存
============
希望官方考虑到此问题,发布官方解决方案:)
转载链接 http://www.thinkphp.cn/topic/29716.html
第一次查询结果会被缓存,第二次查询相同的数据的时候就会直接返回缓存中的内容,而不需要再次进行数据库查询操作。
默认情况下, 缓存有效期和缓存类型是由DATA_CACHE_TIME和DATA_CACHE_TYPE配置参数决定的,但cache方法可以单独指定。
例如:
$Model->where('id=5')->cache(true)->find(); // 自动命名缓存ID,使用系统默认DATA_CACHE_TIME(0=永久有效)
$Model->cache('key',60)->find(); // 自定义缓存ID,60秒后失效
问题:
缓存有效期当然是越久越好,所以默认DATA_CACHE_TIME=0,也就是永久有效。那么问题来了,数据表增删改操作后,如何使查询缓存的数据更新呢?
用S('key',null),那不行,因为查询中用了cache(true),你根本不知道key的具体值,而且如果查询中包含了动态的where查询,那可能会产生多个缓存。
如果设置了缓存有效期cache(true,5),也就是5秒后没有命中该查询缓存的话,缓存会自动失效。这是比较简单的两头兼顾的方法,但是也有问题,在高并发情况下,缓存持续被命中,则缓存持续生效,就没有机会重新从数据表获取增删改后的新数据。对增删改后要求数据查询也立即生效的情景中,缓存刷新成了一个大问题。
综上所述,需改造一下Model类,在select(),find(),getField()方法中,有启用缓存的情况下,增加一个缓存记录逻辑。在add(), save(), delete(), setField()方法中,在有启用缓存的情况下,增加一个清理缓存的逻辑。
==================方法如下:(可作为公开方法放在Model类中,也可以作为函数放在公共函数库function.php中)===================
/**
* 清理数据表查询缓存
*
* 用于解决数据表增删改操作无法刷新查询缓存(特别是cache(true)自动命名的缓存)的问题
* 只需在增删改操作成功时,调用clear_table_caching($table);
* 即可使对应此表的所有查询缓存失效.
*
* 默认在模型的add,save,delete,setField等操作中会自动调用
*
* @param string $table 数据表名称
* @since 1.0 <2015-4-30> SoChishun Added;
*/
function clear_table_caching($table = '') {
$table_caching_keys = F('table_caching_keys');
if (!$table_caching_keys) {
return;
}
// 清理指定表的缓存
if ($table) {
if (isset($table_caching_keys[$table])) {
$values = $table_caching_keys[$table];
foreach ($values as $id) {
S($id, null);
}
unset($table_caching_keys[$table]);
F('table_caching_keys', $table_caching_keys);
}
return;
}
// 清理所有表的缓存
foreach ($table_caching_keys as $values) {
foreach ($values as $id) {
S($id, null);
}
}
F('table_caching_keys', null);
}
/**
* 添加缓存键名到数据表查询集合中
*
* 用于提供clear_table_caching()方法的数据调用
*
* 默认在getField,select,find等方法中自动调用
*
* @param string $table 数据表名称
* @param string $id 缓存键名
* @since 1.0 <2015-4-30> SoChishun Added.
*/
function log_table_cacheing($table, $id) {
$table_caching_keys = F('table_caching_keys');
if ($table_caching_keys && isset($table_caching_keys[$table]) && in_array($id, $table_caching_keys[$table])) {
return; // 如果已经存在则退出
}
$table_caching_keys[$table][] = $id;
F('table_caching_keys', $table_caching_keys);
}
============
使用方法(Model类中):
$this->log_table_cacheing($options['table'], $key); // 记录数据表的缓存键
$this->clear_table_caching($options['table']); // 清除数据表的所有查询缓存
============
希望官方考虑到此问题,发布官方解决方案:)
转载链接 http://www.thinkphp.cn/topic/29716.html
相关文章推荐
- jpa缓存导致无法查询到更新后的数据&android出现ANR的一个解决办法
- tp中save代码正确,无法执行问题,删除缓存试试.---根本的解决办法还需要思考
- 更新安全补丁后无法读取查询导入Excel问题解决说明书
- bugzilla更新出现perl模块无法安装问题解决办法 推荐
- 无法找到SQLFile.SQL导致在SQL Server Studio中无法创建新的查询问题的解决办法
- web网站css,js更新后客户浏览器缓存问题,需要刷新才能正常展示的解决办法
- Glide加载网络图片,服务器内容更新但是Glide缓存无法清理的解决办法
- 为预热准备更新时间列的查询办法,解决原表中没有索引的问题
- Android SDK Manager无法更新问题解决办法
- ibatis中动态查询时缓存问题引起的错误解决办法
- dede5.7联动枚举类型在分类信息中无法更新问题的解决办法
- 提交代码到svn时服务器重启导致svn无法更新问题解决办法
- 无法在同一张表上查询和更新的问题解决方法
- ASP“操作必须使用一个可更新的查询”问题的解决办法
- silverlight缓存无法更新的简易解决办法
- Microsoft JET Database Engine 错误 '80004005' 操作必须使用一个可更新的查询。问题解决办法
- web网站css,js更新后客户浏览器缓存问题,需要刷新才能正常展示的解决办法
- 提交代码到svn时服务器重启导致svn无法更新问题解决办法
- 【转载】----web网站css,js更新后客户浏览器缓存问题,需要刷新才能正常展示的解决办法
- 【转载】web网站css,js更新后客户浏览器缓存问题,需要刷新才能正常展示的解决办法