繁体   English   中英

MariaDB下更新、删除、插入查询慢

[英]Slow Update, Delete and Insert Queries under MariaDB

我们的服务器已从 Ubuntu 16 更新为 Ubuntu 20 和 MariaDB。不幸的是,网站的加载时间变慢了。 通常 MariaDB 应该比 Mysql 快。我发现,很简单,网站上的更新命令有时需要大约 7 秒。 但是,如果我通过 myphpadmin 将这些更新命令直接输入到数据库中,它们只需要 0.0005 毫秒。

在我看来,MariaDB 经常出现更新命令时出现问题。 mysql 从来都不是问题。这是一个查询示例:

UPDATE LOW_PRIORITY users
SET user_video_count = user_video_count + 1
WHERE user_id = 12345

数据库格式为 MyISAM。

我不知道可能是什么原因。 你?

非常感谢你。

它可能像SELECTusers中搜索某些内容一样简单。 注意,InnoDB 不会遇到这个问题。

MyISAM在执行UPDATEINSERTDELETE时必然会锁定表 (还有ALTER和其他 DDL 语句。)如果有很多连接在执行写入甚至SELECTs的任何混合操作,那么锁会级联很长时间。

真正的解决方案,无论是在 MariaDB 还是 [尤其是] 在 MySQL 中,都是切换到 InnoDB。

如果这是对“喜欢”或“观看次数”进行大量计数的情况,则部分解决方案(在任一引擎中)是将此类计数器放在一个单独的并行表中。 这避免了那些简单快速的更新与主表上的其他操作发生冲突。 在人流量极高的区域,收集此类增量并分批应用它们是有必要的。 我认为您的卷不需要那种激进的解决方案。

MySQL 几乎消除了 MyISAM。 MariaDB 可能会在几年后效仿。

为了解决这个问题:

myphpadmin 中的相同查询非常快

问题不在于你如何运行它,而在于同时发生的其他事情。

LOW PRIORITY是 MyISAM 特定的 kludge,有时会起作用。)

MyISAM 进行“表锁定”; InnoDB 做“行锁定”。 因此,Innodb 可以在表上执行许多“同时”操作,而 MyISAM 会在写入发生时立即序列化。

更多(现在专注于 InnoDB。)

可能涉及到的其他一些事情。

如果两个UPDATEs试图同时修改同一行,一个将不得不等待(由于行锁定)。

如果确实有大量事情在发生,延迟可能会一连串地发生。 如果在一个实例中有 20 个连接正在运行,那么它们各自都会减慢彼此的速度。 每个连接都被公平分配,但这意味着它们都变慢了。

SHOW PROCESSLIST查看正在运行的程序——而不是“睡眠”。 “时间”最长的进程(系统线程除外)很可能是这场争吵的始作俑者。

slowlog 可以帮助更深入地研究。 我打开它,使用足够低的long_query_time并等待“事件”发生。 然后我使用pt-query-digest (或mydumpslow -st )找出最慢的查询。 通过更多的努力,人们可能会注意到有很多查询在某一瞬间“缓慢”——甚至可能是“点查询”(如UPDATE... WHERE id=constant )意外地比long_query_time运行得慢。 这表示太多查询和/或某些意外锁定行的查询。 (注意:查询的“时间戳”是查询结束的时间;减去Query_time即可开始。) SlowLog

更多的

正如您所发现的, innodb_flush_log_at_trx_commit = 2在快速执行大量单查询事务时是一个很好的修复。 如果该修复的频率变得太大,那么我上面的评论可能就变得必要了。

=2 和 =0 之间不会有太大的性能差异。

至于innodb_flush_log_at_timeout 请提供 `SHOW GLOBAL STATUS LIKE 'Binlog%commits'

至于innodb_lock_wait_timeout ...我不认为改变它会对你有帮助。 如果您的查询之一由于该超时而中止,您应该记录它发生并重试事务。

听起来您正在使用autocommit = ON运行并且不使用显式事务? 这很好(对于非金钱活动)。 在某些情况下,使用事务可以提高性能——例如人为地将多个查询批处理在一起以避免某些 I/O。 缺点是与其他连接发生冲突的可能性增加。 尽管如此,如果您总是检查错误并重新运行“事务”,那么一切都应该很好。

innodb_flush_log_at_trx_commit

当该设置为“1”(可能是您最初的设置)时,每个更新都会额外写入磁盘以确保数据完整性。 如果磁盘是 HDD(而不是 SDD),则每次更新会增加大约 10 毫秒,因此导致每秒大约 100 次更新的最大值。 有几种解决方法。

  • innodb_flush_log_at_trx_commit = 0 or 2 ,牺牲一些数据完整性。
  • 人为地将多个更新合并到一个事务中,从而将 10 毫秒分散到多个查询中。
  • 根据他们正在做什么和/或他们接触的行明确地组合几个更新。 (在真正繁忙的系统中,这可能涉及其他服务器和/或其他表。)
  • 将计数器移动到另一个表(见上文)——这允许来自主表上更耗时的操作的干扰。 (我没有听到一个明确的例子,但 slowlog 可能已经指出了这一点。)
  • 切换到 SSD 驱动器——更新容量可能增加 10 倍。

我怀疑社交媒体巨头会做上述所有事情。

当您使用 MariaDB 时,您可以使用像 EverSQL 这样的工具来查找丢失的索引或发现冗余索引(例如,您在 user_video_count 上有一个您并不真正需要的索引)

首先我要感谢所有帮助过我的人。 我真的很感激人们尝试投入宝贵的时间。

我想告诉您我是如何设法解决更新、插入和删除查询缓慢的问题的。

我将此值添加到 my.cnf 文件中:

innodb_flush_log_at_trx_commit = 2

在我重启 mysql 服务器后,服务器负载突然下降,更新、插入和删除查询也从大约 0.22222 - 0.91922 秒下降到负载下的 0.000013 秒。 就像之前使用 Myisam 和 Mysql 一样,以及它应该如何使用索引进行如此简单的更新。

我不得不提一下,我已经将所有接收频繁插入或更新命令的表设置为 INNODB,将那些有很多选择的表设置为 ARIA。

由于我们不处理货币交易,如果我们因为以下原因而损失最后几秒对我来说不是问题

innodb_flush_log_at_trx_commit = 2 

我go更进一步。 如果我们输掉了最后 30 秒,我也可以接受。

所以我也设置了:

innodb_flush_log_at_timeout = 30

我目前正在测试

innodb_flush_log_at_trx_commit = 0

但到目前为止,我没有看到明显的改善

innodb_flush_log_at_timeout = 30
innodb_flush_log_at_trx_commit = 0

代替

innodb_flush_log_at_timeout = 1 (default)
innodb_flush_log_at_trx_commit = 2

所以主要目标是:

innodb_flush_log_at_trx_commit = 2

or

innodb_flush_log_at_trx_commit = 0

有谁知道,为什么:

innodb_flush_log_at_timeout = 30
innodb_flush_log_at_trx_commit = 0

并不比刚才快

innodb_flush_log_at_trx_commit = 2

我也不明白,为什么这个设置没有更受欢迎,因为如果许多网站不介意失去一秒钟或更多时间,他们可以在速度方面有很大的改进。

非常感谢你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM