它可能像SELECT
在users
中搜索一样简单.Note,InnoDB不会遇到这个问题.
MyISAM
在做UPDATE
、INSERT
或DELETE
时必然做table lock.(还有ALTER
和其他DDL语句.)如果有很多连接同时进行写操作,甚至是SELECTs
次,那么锁可以级联很长时间.
真正的解决方案,无论是在MariaDB中还是在MySQL中,都是切换到InnoDB.
如果这是"喜欢"或"视图"的大量计数,那么部分解决方案(在任一引擎中)是将此类计数器放在一个单独的并行表中.这避免了那些简单而快速的更新与主表上的其他操作发生冲突.在交通量极高的地区,收集此类增量并批量应用是必要的.我认为你的书不需要那种激进的解决方案.
MySQL几乎已经淘汰了MyISAM.马里亚布可能会在几年后效仿.
为了解决这个问题:
在同一个phpadmin查询中
问题不在于如何运行它,而在于同时发生了什么.
(LOW PRIORITY
是MyISAM特有的乱七八糟的说法,有时会奏效.)
MyISAM做"表锁定";InnoDB执行"行锁定".因此,Innodb可以在一个表上执行很多"同时"操作,而MyISAM在一次写操作发生时就会被序列化.
More(现在专注于InnoDB.)
可能涉及的其他一些事情.
如果两个UPDATEs
同时试图修改same row,一个将不得不等待(由于行锁定).
如果真的有大量的事情发生,延迟可能会层出不穷.如果在一个实例中有20个连接正在积极运行,那么它们都会相互减慢速度.每个连接都有一个公平的份额,但这意味着它们的速度都变慢了.
SHOW PROCESSLIST
来查看运行的是什么,而不是"睡眠"."时间"最高的进程(系统线程除外)很可能是引发争吵的原因.
慢波可以帮助潜水更深.我打开它,以足够低的long_query_time
,等待"事件"发生.然后我用pt-query-digest
(或mydumpslow -s t
)找出最慢的查询.再努力一点,你可能会注意到有很多查询在一瞬间"很慢"——甚至可能是"点查询"(比如UPDATE ... WHERE id=constant
)出乎意料地运行得比long_query_time
慢.这表示查询太多和/或某些查询意外锁定了行.(注意:查询的"时间戳"是在查询ended时,减go Query_time
即可开始.)SlowLog
More
正如您所发现的,当快速执行大量单查询事务时,innodb_flush_log_at_trx_commit = 2
是一个很好的解决方案.如果频率变得太大,无法修复,那么我上面的 comments 可能是必要的.
=2和=0之间不会有太大的性能差异.
至于innodb_flush_log_at_timeout
.请提供"显示全局状态,如"Binlog%committes"
至于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倍.
我怀疑社交媒体巨头会做上述所有事情.