Bug #54914 | InnoDB: performance drop with innodb_change_buffering=all | ||
---|---|---|---|
Submitted: | 30 Jun 2010 13:08 | Modified: | 26 Oct 2010 21:52 |
Reporter: | Alexey Stroganov | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: InnoDB storage engine | Severity: | S5 (Performance) |
Version: | 5.5.5 | OS: | Any |
Assigned to: | Marko Mäkelä | CPU Architecture: | Any |
Tags: | ibuf, ibuf, ibuf, ibuf, ibuf_mutex, ibuf_mutex, innodb, innodb, innodb, innodb |
[30 Jun 2010 13:08]
Alexey Stroganov
[7 Jul 2010 17:12]
Inaam Rana
Profiling the test case shows that ibuf mutex becomes hot when 'all' change buffering is used. Alexey will soon upload the test case and I'll look into this after that.
[7 Jul 2010 18:44]
Alexey Stroganov
Test case for the issue
Attachment: bug_icb.pl (application/octet-stream, text), 6.25 KiB.
[7 Jul 2010 18:48]
Alexey Stroganov
test case usage: a) create/populate table and run update scenario perl bug_bci.pl --db-socket=/tmp/mysql.sock --create --update --buffering=all b) create/populate table and run delete scenario perl bug_bci.pl --db-socket=/tmp/mysql.sock --create --delete --buffering=all - it is possible to vary number of loops for update/delete with --coun=<> - it is possible to vary type of buffering with --buffering=<> - it is possible to show INSERT BUFFER STAT with --stat option
[7 Jul 2010 18:49]
Alexey Stroganov
typo: option name =~ s/coun/count/
[7 Jul 2010 21:02]
Mikhail Izioumtchenko
I wonder if we could split the ibuf mutex to have one per buffer pool instance. This wouldn't help for the problem at hand, though, because the test uses single buffer pool.
[9 Jul 2010 16:20]
Inaam Rana
Reproduced by running the test provided: irana@dscczz01:~/downloads$ perl bug_icb.pl --db-socket=/home/irana/install/mysql.sock --create --update --buffering=inserts MySQL 5.5.5 m3, ENGINE: InnoDB Set innodb_change_buffering=inserts BUFFERING: inserts Generating random keys Inserting 100000 rows Inserted 0 rows Inserted 10000 rows Inserted 20000 rows Inserted 30000 rows Inserted 40000 rows Inserted 50000 rows Inserted 60000 rows Inserted 70000 rows Inserted 80000 rows Inserted 90000 rows Time for insert (100000): 148 wallclock secs ( 1.06 usr 0.02 sys + 0.00 cusr 0.00 csys = 1.08 CPU) Time for check table bench1(1): 7 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU) Testing update of keys: start:0 count:15 update with:1 Time for update_of_primary_key_many_keys (inserts:15): 70 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU) Time for check table bench1(1): 8 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU) +-------------------------------------------------------+------------+-------------------+----------------+ | EVENT_NAME | COUNT_STAR | SUM_TIMER_WAIT_MS | AVG_TIMER_WAIT | +-------------------------------------------------------+------------+-------------------+----------------+ | wait/synch/mutex/innodb/ibuf_mutex | 465648 | 3082.2474 | 6619264 | irana@dscczz01:~/downloads$ perl bug_icb.pl --db-socket=/home/irana/install/mysql.sock --create --update --buffering=all MySQL 5.5.5 m3, ENGINE: InnoDB Set innodb_change_buffering=all BUFFERING: all Generating random keys Inserting 100000 rows Inserted 0 rows Inserted 10000 rows Inserted 20000 rows Inserted 30000 rows Inserted 40000 rows Inserted 50000 rows Inserted 60000 rows Inserted 70000 rows Inserted 80000 rows Inserted 90000 rows Time for insert (100000): 165 wallclock secs ( 1.06 usr 0.02 sys + 0.00 cusr 0.00 csys = 1.08 CPU) Time for check table bench1(1): 7 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU) Testing update of keys: start:0 count:15 update with:1 Time for update_of_primary_key_many_keys (all:15): 84 wallclock secs ( 0.01 usr 0.01 sys + 0.00 cusr 0.00 csys = 0.02 CPU) Time for check table bench1(1): 6 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU) mysql> SELECT EVENT_NAME, COUNT_STAR, (SUM_TIMER_WAIT/1000000000) AS SUM_TIMER_WAIT_MS, AVG_TIMER_WAIT FROM EVENTS_WAITS_SUMMARY_BY_EVENT_NAME WHERE EVENT_NAME LIKE '%INNODB%' AND COUNT_STAR > 0 ORDER BY COUNT_STAR DESC; +-------------------------------------------------------+------------+-------------------+----------------+ | EVENT_NAME | COUNT_STAR | SUM_TIMER_WAIT_MS | AVG_TIMER_WAIT | +-------------------------------------------------------+------------+-------------------+----------------+ | wait/synch/mutex/innodb/ibuf_mutex | 982711 | 12291.2528 | 12507494 | Avg. wait for ibuf_mutex roughly doubles and the number of waits also doubles. The total time spend waiting is roughly four times greater when using change_buffering = all.
[3 Aug 2010 13:13]
Marko Mäkelä
Slightly reduce ibuf_mutex contention. Update the merge counters too.
Attachment: bug54914-2.patch (text/x-diff), 5.18 KiB.
[3 Aug 2010 20:27]
Omer Barnir
triage: Hard to follow the exact issue. Is the 'all option expected to be slower or the same? Is this a new feature or exists in 5.1. If so how does it compare to 5.1? Please clarify
[4 Aug 2010 14:53]
Marko Mäkelä
innodb_change_buffering=all is a new feature in 5.5. Before 5.5, InnoDB only buffered inserts (to leaf pages of secondary index B-trees that are not in the InnoDB buffer pool). With "all", it also buffers delete and purge operations. Under certain workloads, InnoDB is slower with innodb_change_buffering=all than with innodb_change_buffering=inserts. The problem appears to be ibuf_mutex contention.
[4 Aug 2010 18:55]
Marko Mäkelä
Same as above, and invoke ibuf_entry_build() before acquiring ibuf_mutex.
Attachment: bug54914-3.patch (text/x-diff), 7.15 KiB.
[4 Aug 2010 21:34]
Inaam Rana
I tried the patch posted by Marko. It doesn't help in reducing the update time. The insert time for building the table, however, shows some improvement (from 160 wall clock secs to 146 wall clock secs). As suspected this patch won't alleviate the reported issue. But the patch in itself is a step in right direction and should be taken in 5.5 IMO.
[5 Aug 2010 13:00]
Inaam Rana
Tried a suggestion by Marko to use row_format=redundant and see if it changes the equation. No significant change noticed.
[9 Aug 2010 8:59]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/115285
[9 Aug 2010 8:59]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/115286
[9 Aug 2010 12:54]
Marko Mäkelä
Untested patch to reduce ibuf_mutex contention further. Perform some dirty reads on purpose.
Attachment: bug54914-4.patch (text/x-diff), 4.91 KiB.
[9 Aug 2010 12:57]
Marko Mäkelä
With performance_schema monitoring on ibuf_mutex, I found two clear hotspots: select SOURCE,COUNT(*) from EVENTS_WAITS_HISTORY_LONG GROUP BY SOURCE; +------------------+----------+ | SOURCE | COUNT(*) | +------------------+----------+ | ibuf0ibuf.c:2494 | 283 | | ibuf0ibuf.c:2632 | 119 | | ibuf0ibuf.c:3326 | 4990 | | ibuf0ibuf.c:3368 | 119 | | ibuf0ibuf.c:3569 | 3832 | | ibuf0ibuf.c:4104 | 657 | +------------------+----------+ These are in ibuf_insert_low(). My latest patch eliminates the ibuf0ibuf.c:3326 by doing a dirty read of ibuf->size (which should not affect correctness). I did not figure out a way to avoid ibuf0ibuf.c:3569 completely. It is the ibuf->empty=FALSE that is protected by ibuf_mutex. (If this patch is not enough, we can try to protect this flag by something else than the ibuf_mutex.)
[9 Aug 2010 16:46]
Marko Mäkelä
With bug54914-3.patch (committed) and bug54914-4.patch (not yet committed), I am seeing some improvement: innodb_change_buffering=inserts: insert: 229 sec check: 34 sec update: 164 sec innodb_change_buffering=all: insert: 248 sec check: 25 sec update: 134 sec Next, I will investigate the insert regression. I did not enable performance_schema for this change yet.
[10 Aug 2010 10:23]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/115386
[10 Aug 2010 10:23]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/115385
[10 Aug 2010 22:51]
Omer Barnir
triage: setting tag to SR55RC based on last comment
[11 Aug 2010 9:33]
Marko Mäkelä
Bug #55035 is a likely duplicate of this.
[25 Aug 2010 9:22]
Bugs System
Pushed into mysql-5.5 5.5.6-m3 (revid:alik@ibmvm-20100825092002-2yvkb3iwu43ycpnm) (version source revid:alik@ibmvm-20100825092002-2yvkb3iwu43ycpnm) (merge vers: 5.5.6-m3) (pib:20)
[30 Aug 2010 8:31]
Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@sun.com-20100830082732-n2eyijnv86exc5ci) (version source revid:alik@sun.com-20100830082732-n2eyijnv86exc5ci) (merge vers: 5.6.1-m4) (pib:21)
[30 Aug 2010 8:34]
Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100830082745-n6sh01wlwh3itasv) (version source revid:alik@sun.com-20100830082745-n6sh01wlwh3itasv) (pib:21)
[26 Oct 2010 22:00]
John Russell
Added to change log: The setting innodb_change_buffering=all could produce slower performance for some operations than the previous default, innodb_change_buffering=inserts.
[26 Oct 2010 22:01]
John Russell
Added to change log: The setting innodb_change_buffering=all could produce slower performance for some operations than the previous default, innodb_change_buffering=inserts.
[26 Oct 2010 22:01]
John Russell
Added to change log: The setting innodb_change_buffering=all could produce slower performance for some operations than the previous default, innodb_change_buffering=inserts.
[26 Oct 2010 22:01]
John Russell
Added to change log: The setting innodb_change_buffering=all could produce slower performance for some operations than the previous default, innodb_change_buffering=inserts.