InnoDB uses an insert buffer to reduce IO for secondary index maintenance on updates and inserts. This is a persistent index of pending changes that must be done for secondary indexes. When a server gets busy, the insert buffer may grow. This line from SHOW INNODB STATUS displays the size of the insert buffer. When it is large, there is more pending IO to be done to flush changes from the insert buffer to the secondary indexes.
Ibuf: size 37, free list len 70989, seg size 71027,InnoDB does not remove deleted rows from a table until they cannot be read by any other transaction. This is done by a background thread. Deleted rows that have not been purged artificially increase the size of a table. They also increase the overhead of table scan operations. This line from SHOW INNODB STATUS displays the amount of work pending for the purge operation.
History list length 30There are two times when you might want to know the value of these variables. When these values are growing, there is more pending IO to be done by background threads. The rate at which the background threads perform this IO is determined by whether the server is currently busy or idle and by an assumption that the server can do 100 IOs per second.
- When an application scans a table in primary key order concurrent with another application that deletes rows in primary key order, the scanning application will encounter rows that have been deleted but not yet removed. If the purge by the background thread does not keep up with the delete application, then the scan application may run much slower than expected. The innodb_max_purge_lag configuration variable may help with this. But the first time you have this problem, it might take a while to recognize.
- When batch application run concurrent with online applications, it is good to rate limit the work done by the batch apps and these variables can be used to determine when the batch app show slow down.
- Display the history list length value in SHOW STATUS so we don't have to parse SHOW INNODB STATUS.
- Display the insert buffer size in SHOW STATUS as well.
- Make the IO capacity of the server a configurable value and derive the max rate of background IO from these threads. This is hardwired to be 100 IOs per second today. Because of this, a server with many disks will take much longer than necessary to flush pending IOs from the insert buffer and to purge deleted rows.


Hi Mark - Regarding the history list length, I had a production server hit a length of 15835. During this time the server's io shoots up along with load, MySQL (v 5.0.79) becomes unresponsive. I believe that this is because InnoDB is frantically purging deleted rows and is being selfish with IO. What is considered a "normal" History list length? And does the Google patches help with this io bottleneck?
ReplyDeleteWatch for long open transactions if possible (ACTIVE X sec from SHOW INNODB STATUS) as they prevent purge from running.
ReplyDeleteI don't think that 15835 is bad.
The IO done by purge should not overwhelm the server. However, the work done might delay other work done by background IO threads and that can then delay work done by MySQL clients. But I don't understand the purge code to be sure about that.
Google patches don't help much with this. I haven't encountered this problem until recently, so I never tried to fix it.
The best thing to do is monitor history list length. You can also set innodb_max_purge_lag to delay insert/update/delete when it grows.
A large history length caused problems for me in one interesting case. One client was deleting rows from a table in PK order while another scanned the table in PK order. The scan client encountered many rows marked as deleted but not yet removed and this made scans slower than expected.