Bug #58974 ha_innobase:info() tries to lock some latches even if HA_STATUS_NO_LOCK is given
Submitted: 16 Dec 2010 13:43 Modified: 19 Jan 2011 0:13
Reporter: Alexey Stroganov Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S5 (Performance)
Version:mysql-5.5-innodb OS:Any
Assigned to: Vasil Dimov CPU Architecture:Any

[16 Dec 2010 13:43] Alexey Stroganov
Description:
While running OLTP_RW workload with very small dataset (1k rows) for mysql-5.5-innodb tree we have observed drop in performance between revisions 3186 and 3262. 

# 5.5.7-rc-r3186
# 5.5.8-r3262
#
# Test: OLTP_RW:throughput, TPS
#
# Server 1 - 5.5.7-rc-1k
# Server 2 - 5.5.7-rc-10k
# Server 3 - 5.5.7-rc-100k
# Server 4 - 5.5.8-1k
# Server 5 - 5.5.8-10k
# Server 6 - 5.5.8-100k
#
#            Server 1 Server 2 Server 3
# Thread       INNODB   INNODB   INNODB
         32   2104.65  2384.02  2483.25

# Thread     Server 4 Server 5 Server 6
         32    INNODB   INNODB   INNODB
              1821.62  2275.09  2464.00

Further analysis showed that regression were introduced in rev.3219 in fix for 
 Bug#53046 dict_update_statistics_low can still be run concurrently on same table.

How to repeat:
Run OLTP_RW test with 1k rows

Suggested fix:
Below is the patch from Vasil that fixes observed drop:
--- storage/innobase/handler/ha_innodb.cc	revid:vasil.dimov@oracle.com-20101205192108-geoyflq34lqt506q
+++ storage/innobase/handler/ha_innodb.cc	2010-12-07 13:59:29 +0000
@@ -8227,13 +8227,15 @@ ha_innobase::info_low(
 			stats.create_time = (ulong) stat_info.ctime;
 		}
 	}
 
 	if (flag & HA_STATUS_VARIABLE) {
 
-		dict_table_stats_lock(ib_table, RW_S_LATCH);
+		if (!(flag & HA_STATUS_NO_LOCK)) {
+			dict_table_stats_lock(ib_table, RW_S_LATCH);
+		}
 
 		n_rows = ib_table->stat_n_rows;
 
 		/* Because we do not protect stat_n_rows by any mutex in a
 		delete, it is theoretically possible that the value can be
 		smaller than zero! TODO: fix this race.
@@ -8278,13 +8280,15 @@ ha_innobase::info_low(
 				ib_table->stat_clustered_index_size)
 					* UNIV_PAGE_SIZE;
 		stats.index_file_length = ((ulonglong)
 				ib_table->stat_sum_of_other_index_sizes)
 					* UNIV_PAGE_SIZE;
 
-		dict_table_stats_unlock(ib_table, RW_S_LATCH);
+		if (!(flag & HA_STATUS_NO_LOCK)) {
+			dict_table_stats_unlock(ib_table, RW_S_LATCH);
+		}
 
 		/* Since fsp_get_available_space_in_free_extents() is
 		acquiring latches inside InnoDB, we do not call it if we
 		are asked by MySQL to avoid locking. Another reason to
 		avoid the call is that it uses quite a lot of CPU.
 		See Bug#38185. */
@@ -8351,13 +8355,15 @@ ha_innobase::info_low(
 					"is different from the number of "
 					"indexes %u defined in the MySQL ",
 					ib_table->name, num_innodb_index,
 					table->s->keys);
 		}
 
-		dict_table_stats_lock(ib_table, RW_S_LATCH);
+		if (!(flag & HA_STATUS_NO_LOCK)) {
+			dict_table_stats_lock(ib_table, RW_S_LATCH);
+		}
 
 		for (i = 0; i < table->s->keys; i++) {
 			ulong	j;
 			/* We could get index quickly through internal
 			index mapping with the index translation table.
 			The identity of index (match up index name with
@@ -8415,13 +8421,15 @@ ha_innobase::info_low(
 				table->key_info[i].rec_per_key[j] =
 				  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
 				  (ulong) rec_per_key;
 			}
 		}
 
-		dict_table_stats_unlock(ib_table, RW_S_LATCH);
+		if (!(flag & HA_STATUS_NO_LOCK)) {
+			dict_table_stats_unlock(ib_table, RW_S_LATCH);
+		}
 	}
 
 	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
 		goto func_exit;
 	}
[21 Dec 2010 22:45] Omer Barnir
triage: setting to TEAMTREE (to be fixed in innodb tree before pushed to main tree)
[22 Dec 2010 21:30] Bugs System
Pushed into mysql-trunk 5.6.1 (revid:alexander.nozdrin@oracle.com-20101222212842-y0t3ibtd32wd9qaw) (version source revid:alexander.nozdrin@oracle.com-20101222212842-y0t3ibtd32wd9qaw) (merge vers: 5.6.1) (pib:24)