| Bug #38996 | Race condition in ANALYZE TABLE | ||
|---|---|---|---|
| Submitted: | 25 Aug 2008 8:39 | Modified: | 13 Nov 3:20 |
| Reporter: | Vasil Dimov | ||
| Status: | Closed | ||
| Category: | Server: InnoDB | Severity: | S3 (Non-critical) |
| Version: | 5.1 | OS: | Any |
| Assigned to: | Satya B | Target Version: | |
| Tags: | analyze race | ||
| Triage: | Triaged: D2 (Serious) | ||
[25 Aug 2008 8:43]
Vasil Dimov
The same race condition exists even in 4.1.22, so it has not been added recently. Probably it has always been there. Not discovered because it is unusual to run more than one ANALYZE TABLE for a given table at the same time.
[26 Aug 2008 18:59]
Miguel Solorzano
Thank you for the bug report.
[1 Oct 14:58]
Vasil Dimov
Fixed by serializing all ANALYZE TABLE inside InnoDB. The serialization is done per server, not per table even though per table would suffice, but it would be too complicated.
[2 Nov 12:33]
Shane Bester
Hi Vasil! Is it possible this bug could cause a crash?
[2 Nov 12:40]
Vasil Dimov
Shane, Potentially yes, I wouldn't bet that it will never ever crash due to this race.
[4 Nov 10:26]
Bugs System
Pushed into 5.1.41 (revid:joro@sun.com-20091104092152-qz96bzlf2o1japwc) (version source revid:kristofer.pettersson@sun.com-20091103162305-08l4gkeuif2ozsoj) (merge vers: 5.1.41) (pib:13)
[11 Nov 7:53]
Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20091110093407-rw5g8dys2baqkt67) (version source revid:alik@sun.com-20091109080109-7dxapd5y5pxlu08w) (merge vers: 6.0.14-alpha) (pib:13)
[11 Nov 8:01]
Bugs System
Pushed into 5.5.0-beta (revid:alik@sun.com-20091109115615-nuohp02h8mdrz8m2) (version source revid:svoj@sun.com-20091105122958-jyqjx9xus8v4e0yd) (merge vers: 5.5.0-beta) (pib:13)
[13 Nov 3:20]
Paul DuBois
Noted in 5.1.41, 5.5.0, 6.0.14 changelogs. Simultaneous ANALYZE TABLE operations for an InnoDB tables could be subject to a race condition.

Description: During ANALYZE TABLE the function btr_estimate_number_of_different_key_vals() is called and it modifies the array index->stat_n_diff_key_vals[]. This is not protected by any mutex and several ANALYZE TABLE can edit the array simultaneously. The backtrace is the following: #3 0x00000000007903fe in btr_estimate_number_of_different_key_vals (index=0x18160a8) at btr/btr0cur.c:3173 #4 0x00000000007b0e3d in dict_update_statistics_low (table=0x18150a8, has_dict_mutex=0) at dict/dict0dict.c:4024 #5 0x00000000007b0efa in dict_update_statistics (table=0x18150a8) at dict/dict0dict.c:4053 #6 0x000000000077fd96 in ha_innobase::info (this=0x252a010, flag=28) at handler/ha_innodb.cc:6597 #7 0x0000000000778cde in ha_innobase::analyze (this=0x252a010, thd=0x2283000, check_opt=0x22853a8) at handler/ha_innodb.cc:6798 #8 0x00000000006d344b in handler::ha_analyze (this=0x252a010, thd=0x2283000, check_opt=0x22853a8) at handler.cc:3079 #9 0x00000000006e936c in mysql_admin_table (thd=0x2283000, tables=0x25220d8, check_opt=0x22853a8, operator_name=0x9c9366 "analyze", lock_type=TL_READ_NO_INSERT, open_for_modify=true, no_warnings_for_error=false, extra_open_options=0, prepare_func=0, operator_func= {__pfn = 0x6d3410 <handler::ha_analyze(THD*, st_ha_check_opt*)>, __delta = 0}, view_operator_func=0) at sql_table.cc:4338 #10 0x00000000006ea049 in mysql_analyze_table (thd=0x2283000, tables=0x25220d8, check_opt=0x22853a8) at sql_table.cc:5008 #11 0x00000000005d1cdf in mysql_execute_command (thd=0x2283000) at sql_parse.cc:2799 #12 0x00000000005d7a7b in mysql_parse (thd=0x2283000, inBuf=0x2522010 "analyze table t", length=15, found_semicolon=0x7ffffebb5dd0) at sql_parse.cc:5656 #13 0x00000000005d86af in dispatch_command (command=COM_QUERY, thd=0x2283000, packet=0x2297001 "", packet_length=15) at sql_parse.cc:1137 #14 0x00000000005d9844 in do_command (thd=0x2283000) at sql_parse.cc:794 This should be serialized somewhere. How to repeat: Could be tricky. btr_estimate_number_of_different_key_vals() is called not only during ANALYZE TABLE but also when the table is opened. I stepped in gdb until btr_estimate_number_of_different_key_vals() was called from ANALYZE TABLE (the above backtrace), executed "call sleep(100)" from gdb and then executed another ANALYZE TABLE from a second mysql client. Suggested fix: Serialize in InnoDB or in MySQL layer.