Bug #72584 storage/inobase/dict/dict0dict.cc
Submitted: 8 May 2014 19:53 Modified: 12 May 2014 17:11
Reporter: 徹 赤松 Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:5.7.4 OS:Linux
Assigned to: CPU Architecture:Any
Tags: dict_table_remove_from_cache_low, dict0dict.cc, innodb

[8 May 2014 19:53] 徹 赤松
Description:
i am reading source code of InnDB storage engine version 5.7.4 now.
When i read dict_table_remove_from_cache_low function in storage/innobase/dict/dict0dict.cc, i found a bug.

storage/innobase/dict/dict0dict.cc
  1760  dict_table_remove_from_cache_low(
  1761  /*=============================*/
  1762          dict_table_t*   table,          /*!< in, own: table */
  1763          ibool           lru_evict)      /*!< in: TRUE if table being evicted
  1764                                          to make room in the table LRU list */
  1765  {
  ...
  1783          /* Remove the foreign constraints from the cache */
  1784
x 1785          for (foreign = UT_LIST_GET_LAST(table->foreign_list);
  1786               foreign != NULL;
x 1787               foreign = UT_LIST_GET_LAST(table->foreign_list)) {
  1788
  1789                  dict_foreign_remove_from_cache(foreign);
  1790          }
oooooo
o 1785          for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
o 1787               foreign = UT_LIST_GET_NEXT(foreign_list, foreign);

  ...
  1802          /* Remove the indexes from the cache */
  1803
x 1804          for (index = UT_LIST_GET_LAST(table->indexes);
  1805               index != NULL;
x 1806               index = UT_LIST_GET_LAST(table->indexes)) {
  1807
  1808                  dict_index_remove_from_cache_low(table, index, lru_evict);
  1809          }
oooooo
o 1804          for (index = UT_LIST_GET_FIRST(table->indexes);
o 1806               index = UT_LIST_GET_NEXT(indexes, index);

Please check and i am pleased if you can reply.

How to repeat:
i can not repeat it, but remove only key on the LAST LIST.
So many foreign_keys and indexes remain on the cache, it is no good. 

Suggested fix:
i think change under 4 lines.
Line number is in mysql version-5.7.4.

o 1785          for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
o 1787               foreign = UT_LIST_GET_NEXT(foreign_list, foreign);

o 1804          for (index = UT_LIST_GET_FIRST(table->indexes);
o 1806               index = UT_LIST_GET_NEXT(indexes, index);
[9 May 2014 13:28] MySQL Verification Team
Mr. Akamatsu,

Thank you very much for your interest and for the analyzing our code. Please, do that in future too, as bugs can creep in quite easily.

However, in this case, there is not bug. Linked lists of both foreign indices and indigenous indices are removed in both cases from last to the first and not from the first to the last one. Let us take the example of the indices.

A macro UT_LIST_GET_LAST gets the last index in the linked list. That is the macro that initializes the counter. Then the function dict_index_remove_from_cache_low(table, index,
lru_evict) is called. In that function, the last index in the linked list is removed, with a macro  UT_LIST_REMOVE. Hence, in the next iteration, the macro UT_LIST_GET_LAST gets a NEW index that is the next one in the list, which is last, so the removal progresses from the last index to the first one.

Same process is done for foreign indices.
[12 May 2014 17:11] 徹 赤松
Dir Sinisa Milivojevic,

Thank you for the polite reply.