在SHOW PROCESSLIST
中 - 它显示大约30多行已被锁定几秒钟然后更新。
有没有办法加快更新速度?
示例:
+------+-----------------+-----------+----------------+---------+------+----------+-------------------------------------------------------------------------------
| Id | User | Host | db | Command | Time | State | Info
+------+-----------------+-----------+----------------+---------+------+----------+--------------------------------------------------------------------------------
| 265 | user | localhost | xxxxxxxxxxxxxx | Query | 15 | Updating | UPDATE data SET status = '1', error = 'Unknown error' WHERE f= 0xxxxx
| 269 | user | localhost | xxxxxxxxxxxxxx | Query | 17 | Updating | UPDATE data SET status = '1', error = 'Invalid ....' WHERE f= 0xxx
| 280 | user | localhost | xxxxxxxxxxxxxx | Query | 7 | Updating | UPDATE data SET status = 1 WHERE f = 0xxxx
| 300 | user | localhost | xxxxxxxxxxxxxx | Query | 1 | Updating | UPDATE data SET status = '1', error = 'Unknown ....' WHERE f= 0xx
| 314 | user | localhost | xxxxxxxxxxxxxx | Query | 13 | Updating | UPDATE data SET status = '1', error = 'Invalid....' WHERE f= 0xxxx
| 327 | user | localhost | xxxxxxxxxxxxxx | Query | 11 | Updating | UPDATE data SET status = '1', error = 'Unknown ....' WHERE f= 0xxxx
| 341 | user | localhost | xxxxxxxxxxxxxx | Sleep | 2 | | NULL
| 350 | user | localhost | xxxxxxxxxxxxxx | Query | 7 | Updating | UPDATE data SET status = '1', error = 'Unknown ....' WHERE f= 0xxx
| 360 | user | localhost | xxxxxxxxxxxxxx | Query | 5 | Updating | UPDATE data SET status = 1 WHERE f = 0xxxx
有很多更新 - 我使用的是InnoDB
,有些字段是index
。
在数据表中,在PHP CLI脚本中循环(在Linux中的后台/进程中运行)时,需要更新超过500,000行。
答案 0 :(得分:1)
InnoDB在每个INSERT / UPDATE中使用IO来确保de ACID属性,您可以将定义innodb_flush_log_at_trx_commit
变量的此行为更改为2,因此MySQL每秒使用IO而不是每次提交(在许多情况下非常好)。
更多信息here
答案 1 :(得分:1)
确保f
列已编入索引,以便WHERE子句正在使用它。否则,您将在每次更新时扫描整个表格。
尝试对更新进行分组,以便您可以一次设置一行UPDATE而不是一行。
确保您没有使用自动提交。尝试每次交易执行多项更改。
确保您已调整InnoDB。大多数人使用innodb_buffer_pool_size
,innodb_log_file_size
和innodb_io_capacity
的默认值。默认值未针对高性能进行调整。
设置innodb_flush_log_at_trx_commit=2
以减少fsyncs,正如@Paulo H.建议的那样。
答案 2 :(得分:0)
快速解决方法是策略性地添加一个sleep()调用,因此当你跨过数千行时,你不会压倒数据库。一个好的做法是每行睡眠1/100秒,然后每100行睡5秒。这是我参与的系统的一般规则,因此您可能需要稍微修改这些设置以使它们为您工作。
我遇到的一个问题是您的用户表存储错误列的文本值。文本列的性能不如int列,更不用说如果您需要更新错误值,可能会影响数千条记录。
答案 3 :(得分:0)
InnoDB
是您正在执行的操作的正确引擎,因为它会锁定行,而不是整个表。我建议您确保已正确索引表格,使用正确的列类型并且它们的大小与它们所需的一样小(因此,无论是真还是假,都应将其存储为 unsigned int 1 )。