Transients应该过期并被删除。但是,我看到此处理的唯一方法是当瞬变过期并被请求时,然后在请求期间将其删除。
如果瞬变过期但在此之后再没有请求怎么办?从食典中的描述,我认为这意味着某种垃圾回收。现在我不太确定,找不到执行此操作的任何代码。
那么它将永远永远卡在数据库中吗?
#1 楼
现在是从WordPress 3.7开始,数据库升级时会删除过期的瞬变,请参阅#20316
旧答案
如果有人否则无法向我展示,看来瞬变毕竟不是垃圾收集。更糟糕的是,与选项不同,它们不能保证存储在数据库中。因此,没有可靠的方法来获取所有瞬态的列表以检查它们是否到期。
如果数据库用于存储,则一些临时代码可以进行垃圾回收:
add_action( 'wp_scheduled_delete', 'delete_expired_db_transients' );
function delete_expired_db_transients() {
global $wpdb, $_wp_using_ext_object_cache;
if( $_wp_using_ext_object_cache )
return;
$time = isset ( $_SERVER['REQUEST_TIME'] ) ? (int)$_SERVER['REQUEST_TIME'] : time() ;
$expired = $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout%' AND option_value < {$time};" );
foreach( $expired as $transient ) {
$key = str_replace('_transient_timeout_', '', $transient);
delete_transient($key);
}
}
评论
$ time = $ _SERVER ['REQUEST_TIME'];然后在SQL查询中使用$ time-不要这样做。 $ _SERVER变量/值应更仔细地处理以防止SQL注入。
– hakre
2011年1月10日12:01
@hakre hm ...我是从有关PHP性能的演示文稿中挑选出来的,推荐使用time()来推荐它,这可能会导致错误(执行不是自然而然的)。请求时间是由PHP自己设置的,它不是来自用户提供的任何数据。为什么会出现此漏洞?
–稀有
2011年1月10日12:08
@Rarst:我并不是说您不应该使用它,您应该确保将它安全地编码以在SQL查询中使用。您应该对来自外部源的每个变量执行此操作。 $ _SERVER变量可能未按预期设置,而是由请求用户设置。我只想传播一些好的编码实践。与往常一样,要了解可用性的真实状态,请参阅文档。例如,对于PHP 4,此类变量不存在,并且可能会被自定义标头或环境变量覆盖-php.net/manual/en/reserved.variables.server.php
– hakre
2011年1月10日12:12
@hakre已修复(我认为),感谢PHP4提醒btw(我等不及WordPress放弃对此的支持)
–稀有
2011年1月10日,12:19
在我眼里看起来好多了;)。我们希望time()和负整数没有问题,它们可能会偶然删除所有或没有瞬变。永远不要相信正在运行的系统:P
– hakre
2011年1月10日12:26
#2 楼
通过重新措辞和重新设置格式,将讨论中的一些评论转变为答案。.基本上,归结为,除非您有极端的案例,否则它们不会确实需要“收集垃圾”。如果您从未获取过它们,那么它们是否存在都没关系。
请注意,瞬态默认情况下存储在选项表中。在基本安装中,选项表中可能包含100个条目。每个瞬态都会添加两个条目,但是即使您有数千个条目,它们也不会影响网站速度,因为它们不会自动加载。
在启动时,WordPress会将选项加载到内存中,但是仅加载启用了自动加载标记的选项。瞬态不了解这一点,因此也不会加载到内存中。只有稍后实际使用的瞬态会产生成本。
从数据库的角度来看,选项表在选项ID和选项名称上都有索引。瞬态总是根据名称(键)加载的,因此对它们的查找始终是对单个唯一键值的简单选择。因此,查找为O(log(n)),并且超快。使用log(n)的Big-O,您必须先进入成千上万的行,然后它才变得引人注目。坦白地说,查询的设置和拆卸以及实际数据传输的开销要长得多。通过比较,查询本身的运行时间基本上为零。因此,简单地拥有多余的未使用行对使用额外的磁盘空间不会有任何影响。
在数据库中建立索引是那些对那些没有知识的人没有意义的深层想法之一真正了解幕后发生的事情。数据库旨在从头开始快速进行数据检索,并且可以毫无问题地处理此类问题。这是一本不错的书:http://en.wikipedia.org/wiki/Index_(数据库)
现在,以最明显的方式进行清理(在它们上调用SQL DELETE)实际上并没有从数据库中删除它们。它只是将它们从索引中删除,并将该行标记为“已删除”。同样,这就是数据库的工作方式。要实际清除磁盘空间,您必须继续然后在之后执行OPTIMIZE TABLE,这不是一项快速的操作。这需要时间。可能花了更多时间。总的来说,这可能不足以节省CPU时间。
如果您遇到某种情况导致连续插入未使用的新瞬态,那么您需要找到根本的问题。是什么插入这些瞬变?他们使用的是变更键还是变异键?如果是这样,那么导致此问题的插件或代码基本上应该固定为不这样做。这样做会更有帮助,因为未正确创建它们的代码也可能没有检索到它们,因此完成了比其所要做的更多的工作。
另一方面,在某些情况下,可能会为每个帖子都创建瞬态。这确实可以完全接受。我自己在SFC中进行此操作,以存储来自Facebook的传入评论。每个帖子都有一个与之关联的潜在瞬变,这意味着每个帖子有两个额外的行。如果您有1万条帖子,那么选项表中(最终)将有2万行。这并不坏,也不会很慢,因为同样,就数据库真正关心的而言,100行和20,000行之间的差异很小。全部索引。快得快。次毫秒。
当您开始进入数百万行时,我会担心。当上述几百兆的选项表大小的增加,那么我会关注不够仔细看看。但是总的来说,除了极端情况,这不是问题。对于比拥有数十万个帖子的大型新闻网站这样的小问题来说,这绝对不是问题。对于任何足以解决问题的站点,您都应该使用某种外部对象缓存,在这种情况下,瞬态会自动存储在此处而不是存储在数据库中。
评论
注意:没有到期的瞬变会自动加载,默认情况下没有到期,因此,在应用程序/插件创建大量瞬变且未设置到期的情况下,它们将在每次加载页面/加载时使用大块内存。
– Webaware
13年7月29日在0:48
是的,但这是默认设置。因此,许多插件作者都添加了未到期的瞬态。
– Webaware
13年7月30日在0:19
好吧,这里的解决方案很简单:不要使用这些插件。他们做错了。暂态不能用作会话,您不应在没有有意义的期限的情况下使用它们,并且它们不应具有突变或更改键。
–奥托
13年7月30日在16:12
说7天。如果插件/主题作者想要更大或更小的东西,他们会指定它。如果他们想要自动加载,则不必为到期时间(= infinity)指定0,但这就是他们当前使用expiration参数作为yes / no autoload参数承担双重职责的结果。无论哪种方式,默认到期都不应该导致autoload = yes作为默认值。那只是自找麻烦。
– Webaware
13年8月1日在1:02
我认为,未指定有效期将引发致命错误并破坏站点。但后来我不负责。没有到期的瞬态是愚蠢的,毫无意义。如果要使用对象缓存,则只需将对象缓存直接与wp_cache函数一起使用。就是说,有一些票证可以让未来版本的WordPress清理旧的瞬态,主要是因为它比其他任何东西都“难看”。
–奥托
2014年3月19日下午5:20
#3 楼
奥托-我再也不同意你的看法。问题是,最终,在所有这些瞬变中,表的大小变得荒谬。不需要花费数百万行就可以解决。我当前正在处理具有超过13万行的选项表,该表经常挂起。因为value字段是大文本类型,所以即使仅查找“自动加载”行也成为性能的噩梦。这些值字段与其余的行数据分开存储。
即使从逻辑上讲它是同一张表的一部分,也必须进行联接才能提取所需的行。现在,由于需要的数据分布在磁盘上的所有位置,因此永久连接需要很长时间。分析(对于MySQL使用jet profiler)已经证明了这一点。
将自动加载添加到群集密钥可能有助于解决此问题。例如,基于自动加载描述(ID ASC)的群集,将允许所有自动加载行首先在磁盘上聚集在一起。甚至我仍然认为您从数据库的角度来看正承受着巨大的压力。
我个人认为该系统的设计很糟糕。选项表似乎已经变成了很多事情的通用工具。如果value字段足够小,可以与该行数据的其余部分包含在同一页上,并且可以有效地对其进行索引,则可以。不幸的是,事实并非如此。设计此方法的人需要回到DB101类。
评论
是的,但是请考虑一下,当WordPress开发开始时,没有人认为使用options表作为其数据存储将拥有成千上万的插件:)
–onetrickpony
2011年12月2日于20:39
@onetrickpony,这就是为什么务必要花时间并正确地做事很重要,无论您希望某天是否变得如此巨大:)
–马哈茂德·古德西(Mahmoud Al-Qudsi)
17年12月11日在23:16
评论
从理论上讲,应在运行cron时将其删除(如果它们已过期)@雄心勃勃的变形虫是的,我有点提到这个问题。我的意思是-创建瞬态并不假定或保证将要请求它。强调最初的问题-如果我从未得到过,何时以及是否过期的瞬变会被删除?
假设您清除了过期的数据,但是是的,您是对的,在某些情况下,数据永远都不会被删除。就像删除使用瞬态的小部件一样。您应该为此在票上提交票证:)
@Rarst-编写补丁并提交给trac听起来很完美?
相关的追踪票:core.trac.wordpress.org/ticket/20316