在一个繁忙的可湿性粉剂网站上,我们正在运行一个安全插件,它在处理网站(iThemes安全专业版)上的潜在攻击时,在wp_options中创建一个临时锁条目,其方式如下:
$result = $wpdb->query( $wpdb->prepare(
"INSERT IGNORE INTO `$wpdb->options`
(`option_name`, `option_value`, `autoload`)
VALUES (%s, %s, 'no') /* LOCK */",
$lock, $release_at ) ); 在攻击频繁出现的偶尔情况下,这会导致PHP日志中的条目如下:
[08-Apr-2021 05:17:22] [pool www] pid 69444
script_filename = /var/www/blog/index.php
[0x00007fc499214890] mysqli_query() /var/www/blog/wp-includes/wp-db.php:2056
[0x00007fc499214820] _do_query() /var/www/blog/wp-includes/wp-db.php:1945
[0x00007fc499214740] query() /var/www/blog/wp-content/plugins/ithemes-security-pro/core/lib.php:758
...etcmysql-slow日志(与log_queries_not_using_indexes一起在2秒内启用)中没有任何条目表明这会导致查询速度变慢,但这里显然存在问题。据我所知,查询或表看起来不会造成问题:
CREATE TABLE `wp_options` (
`option_id` bigint unsigned NOT NULL AUTO_INCREMENT,
`option_name` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`option_value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`autoload` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'yes',
PRIMARY KEY (`option_id`),
UNIQUE KEY `option_name` (`option_name`),
KEY `autoload` (`autoload`)
) ENGINE=InnoDB AUTO_INCREMENT=161904628 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
(Currently 700 records in the table)它通常对应于对站点的所有请求都以504ing结束的一段时间,因为apache线程被占用,等待这些锁条目被清除(假设)。错误日志显示如下:
[Thu Apr 08 05:17:25.952586 2021] [proxy_fcgi:error] [pid 62595:tid 140674875750144] (70007)The timeout specified has expired: [client X.X.X.X:22504] AH01075: Error dispatching request to : (polling)我一直没能在它发生的时候捕捉到它,但之前它导致了OOM Killer关闭PHP,这经常使服务器崩溃。服务器实例最近已经变得更大,以试图避免这种情况,并且在最近一次发生时,它确实在大约20分钟后恢复。但这仍然是一个问题。
服务器本身是一台AWSt2中型服务器,有4 4GB内存,运行一个繁忙的博客和几个安静的博客,DB在单独的r6g.2xlarge上,64 4GB内存,托管各种内部站点的mySQL数据库负载,没有任何慢查询报告,也没有慢PHP脚本的类似问题。只有一个博客,来自这个插件,只有一个查询。
有人能解释一下这里发生了什么吗?谢谢
第一次编辑:
From https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html“如果发生重复键错误,则在重复索引记录上设置共享锁。如果多个会话已具有排它锁,则多个会话尝试插入同一行时,这种共享锁的使用会导致死锁。”
由于锁定名称在插件中是从攻击类型、任何登录用户和来源IP派生的,因此可能会发生这种情况。
它不是使用SELECT来识别wp_options中是否存在锁记录,如果找到则不采取任何操作,而是在每次传递时使用INSERT IGNORE INTO,因此当攻击者快速访问站点时,这可能会导致mySQL链接中描述的死锁。我将深入研究这一点,但这可能是插件支持团队的一个问题。
发布于 2021-04-09 05:17:19
这应该是一个评论,但它太长了。
与log_queries_not_using_indexes一起在2秒内启用的
这没有什么意义。如果您对实际加速数据库/减少负载感兴趣,那么您需要记录所有查询并分析活动模式。修复单个查询性能问题可能只会将问题推到其他地方。
它通常对应于对站点的所有请求都以504ing结束的一段时间
既然您有明确的证据表明PHP过载并且无法执行脚本,那么为什么您认为包含您的查询的脚本实际上正在被调用,并且正在执行查询,并且查询的运行时间比预期的要长,并且DBMS没有记录这一事实?
它已经导致了OOM Killer关闭
您的服务器配置错误。它应该设置为将工作负载限制在它可以提供的物理资源上。
经常使服务器崩溃的
是的,OOM杀手将在主机上终止至少一个服务器进程。没有关于它的“经常”。除非“服务器”指的是主机-在这种情况下,不是。
Wordpress是一只笨拙的恐龙。这是一个完全错误的地方,放置旨在保护恐龙免受攻击的代码。
https://stackoverflow.com/questions/67000509
复制相似问题