Viewing all changes in revision 3470.

  • Committer: Mark Callaghan
  • Date: 2010-04-23 20:46:42 UTC
  • Revision ID: mdcallag@gmail.com-20100423204642-ki1vkhigcn08q43q
Don't collect table stats until after LOCK_open is unlocked when creating a table handler instance.
Only InnoDB implements the optimization. I don't know if other engines need the fix. The fix is to:
* during open_table() call handler::open_fast() instead of handler::open()
* after LOCK_open has been unlocked call handler::open_deferred()

This fixes bugs:
(these are really the same bug, someone filed a duplicate)

This might fix other race conditions where dict_update_statistics_low ran concurrently
for the same InnoDB table.

With this change there can be concurrent calls to ha_innobase::info for the same table
(using different handler instances). All data updated during these calls are free of
races with one exception. They are free of races because they update data in the handler
instance. The one race is when HA_STATUS_TIME is set and dict_update_statistics is called.
A similar problem exists in ha_innobase::open when dict_table_get_is called as that can call
dict_update_statistics. This is fixed by using a mutex in dict_update_statistics_low. Also,
remove the use analyze_mutex to prevent one case in which concurrent collection of per-table
stats can occur -- see bugs.mysql.com/bug.php?id=38996. That was a partial bug fix and used
a global mutex. The full fix is to add a mutex to dict_table_struct and use that in
dict_update_statistics_low. A boolean parameter is added to a few functions to indicate
whether stats collection should not be deferred. The default value is TRUE. Only calls on
the following path may use FALSE:
  open_table -> open_unireg_entry -> open_table_from_share -> ha_open -> ha_innobase::open
dict_update_statistics has been changed to take a 'force' parameter that indicates whether
statistics are to be collected when they already exist. All callers are updated to use that. 

QPS for sysbench readonly doing connect,fetch 1 row,disconnect and 1 to 1024 concurrent connections
5145dev does not have the change, 5145lockopen does
uses 200M innodb buffer pool for ~8G database
sysbench table changed to have secondary index on each column (3 in total)
  45 92 182 368 763 1429 2096 2969 3550 3540 3569 5145dev
  43 89 185 385 702 1191 1945 3075 3530 3614 3545 5145lockopen

Internal stats          5145lockopen 5145dev
Command_seconds         103342       103920 == seconds running SQL commands
Opened_tables_seconds      487         1345 == seconds in open_table() holding LOCK_open
Opened_tables           994171      1063858
Threads_created           1199         1248 

A second performance test was run:
* 8,000 Innodb tables with 5 secondary indexes per table and 1MB of disk space per table
* create tables, restart mysqld, query 1 row from each table
* 8 concurrent connections and 1,000 tables per connection
162 seconds with the change
337 seconds without the change

expand all expand all

Show diffs side-by-side

added added

removed removed

Lines of Context: