与MediaWiki 1.31一样,没有批量删除垃圾邮件用户的扩展(只有手动合并和删除)。我们将通过 MySQL 删除用户,但有警告指出此方法可能会因为引用的表而破坏您的数据库。删除用户表/行时,是否有办法确保没有引用受到损害?有什么经验或建议吗?
今天我遇到了一个旧的Mediawiki 1.23的问题,并搜索了一下。
- 媒体维基手册:数据库布局
- 数据库架构图
- 手册:页表 - 删除页面及其在文本和修订表中的关系
根据上面的信息,我做了一些实验。
首先,我想评估一下损坏情况:
外部链接
select count(*) from externallinks
select convert(el_to using utf8) as href
from externallinks l
那里有大约 150.000 个外部链接
用于查找用户的 SQL 查询
select
convert(user_name using utf8) as name,
convert(user_touched using utf8) as time,
user_editcount
from user
order by 2 desc
就我而言,所有垃圾邮件用户都在同一时间段内创建。
SQL查询,带有页面,修订,文本和用户表的连接。
select
convert(u.user_name using utf8) as username,
p.page_id,
convert(p.page_title using utf8) as pagetitle,
r.rev_user as userid,
convert(t.old_text using utf8) as text
from page p
inner join revision r
on p.page_id=r.rev_page
inner join user u
on r.rev_user=u.user_id
inner join text t
on r.rev_text_id=t.old_id
SQL 查询以查找每个用户的修订数:
select count(*),u.user_id,convert(u.user_name using utf8) as username
from revision r
inner join user u
on r.rev_user=u.user_id
group by 2
order by 1 desc
就我而言,幸运的是,所有"好"页面仅由一个用户创建,user_id=1,因此我可以通过以下方式评估损害:
select count(*) as textcount from text where old_id in (select rev_text_id from revision where not rev_user in (1));
结果给了我超过五十万次点击,这意味着删除最好以逐步的方式完成:
select count(*) as textcount from text where old_id in (select rev_text_id from revision where not rev_user in (1));
set autocommit=0;
start transaction;
delete from text where old_id in (select rev_text_id from revision where not rev_user in (1)) limit 2000;
commit;
请注意,2000 的限制已经导致大约 2 分钟的运行时间。 所以我必须运行上面的 SQLStatement 大约 250 次,每次等待 2 分钟......
如果遇到删除计时问题,可以考虑以下提示:
- 如何提高大型InnoDB表的DELETE FROM性能?
您可以通过以下方式查看我们的表格状态:
show table status from <wiki-databasename>;
在我的情况下,使用INNODB的表。
我尝试将innod_buffer_pool_size增加到 128 MByte,但这并没有产生积极的影响。删除仍然很慢。
我仍然会尝试完成此操作并通过删除相关行来工作
- 外部链接
- 校订
- 页
我还检查了/var/lib/mysql/中的文件。由于我每个表都有 innodb 文件,我看到很多表都变得非常大。
所以调查
- https://www.percona.com/blog/2013/09/25/how-to-reclaim-space-in-innodb-when-innodb_file_per_table-is-on/
并开始
optimize table text
这需要8个小时才能完成。
幸运的是,就我而言,它并不是一个真正的生产维基。我只是想检查该方法的可行性,看起来它在很大程度上取决于所涉及的行数。
基于 API 和基于维护的方法可能更有效,具体取决于具体方案。
你试过这个吗:https://www.mediawiki.org/wiki/Manual:RemoveUnusedAccounts.php?
这是一个内置的 scipt 可以毫无问题地删除未使用的帐户。阅读上面链接中的说明。