Bug #94379 innobase_create_handler new a ha_innobase will not delete
Submitted: 18 Feb 2019 12:21 Modified: 28 Feb 2019 14:05
Reporter: long jian Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:8.0.14 OS:CentOS
Assigned to: CPU Architecture:x86

[18 Feb 2019 12:21] long jian
Description:
I found innobase_create_handler new a ha_innobase for every innodb table when start a connection, but won't delete it when quit the connection. When drop the table, all these ha_innobase object will delete. Is there a memory leak?

How to repeat:
1. CREATE TABLE `example` (
  `id` int(11) NOT NULL,
  `textfield` varchar(20) NOT NULL,
  `number` int(11) NOT NULL
);
2. gdb attach mysqld
3. break on ha_innobase::ha_innobase and ha_innobase::~ha_innobase
4. execute "./bin/mysql -uroot mysql" and "\q" several times,will break on ha_innobase::ha_innobase several times.
5. execute "drop table example". will break on ha_innobase::~ha_innobase several times.
[26 Feb 2019 14:27] MySQL Verification Team
Hi,

Thank you for your bug report.

First, you will get several code stops at that breakpoint, since there are several threads in 8.0.

Second, when you write about allocating and not freeing some object, would you be so kind to point exactly the file names and line numbers of the code in 8.0.14.
[28 Feb 2019 10:07] long jian
Repeat is complicated, because there are too many innodb tables. I was check point of ha_innobase object. Here is my Stack, hope it is helpful. 

Connect mysql:
#0  ha_innobase::ha_innobase (this=0x7f12604293d8, hton=0x8b8b200, table_arg=0x7f12603f9248) at /home/jlong/data/Workspace/mysql814/storage/innobase/handler/ha_innodb.cc:2713
#1  0x0000000004542574 in innobase_create_handler (hton=0x8b8b200, table=0x7f12603f9248, partitioned=false, mem_root=0x7f1260364e30) at /home/jlong/data/Workspace/mysql814/storage/innobase/handler/ha_innodb.cc:1502
#2  0x0000000003335b95 in get_new_handler (share=0x7f12603f9248, partitioned=false, alloc=0x7f1260364e30, db_type=0x8b8b200) at /home/jlong/data/Workspace/mysql814/sql/handler.cc:588
#3  0x000000000314cb2f in open_table_from_share (thd=0x7f126000fb60, share=0x7f12603f9248, alias=0x7f12603f9a88 "example", db_stat=39, prgflag=8, ha_open_flags=0, outparam=0x7f12603645a0, is_create_table=false, table_def_param=0x7f126041ced0)
    at /home/jlong/data/Workspace/mysql814/sql/table.cc:2802
#4  0x0000000002f5dc6f in open_table (thd=0x7f126000fb60, table_list=0x7f12f81a6b60, ot_ctx=0x7f12f81a6870) at /home/jlong/data/Workspace/mysql814/sql/sql_base.cc:3345
#5  0x0000000002f616e0 in open_and_process_table (thd=0x7f126000fb60, lex=0x7f126018ac80, tables=0x7f12f81a6b60, counter=0x7f126018acd8, prelocking_strategy=0x7f12f81a6970, has_prelocking_list=false, ot_ctx=0x7f12f81a6870)
    at /home/jlong/data/Workspace/mysql814/sql/sql_base.cc:5000
#6  0x0000000002f62af7 in open_tables (thd=0x7f126000fb60, start=0x7f12f81a6930, counter=0x7f126018acd8, flags=1024, prelocking_strategy=0x7f12f81a6970) at /home/jlong/data/Workspace/mysql814/sql/sql_base.cc:5645
#7  0x0000000002f64556 in open_tables_for_query (thd=0x7f126000fb60, tables=0x7f12f81a6b60, flags=1024) at /home/jlong/data/Workspace/mysql814/sql/sql_base.cc:6522
#8  0x000000000308be10 in mysqld_list_fields (thd=0x7f126000fb60, table_list=0x7f12f81a6b60, wild=0x7f12603010a8 "") at /home/jlong/data/Workspace/mysql814/sql/sql_show.cc:859
#9  0x000000000300aa69 in dispatch_command (thd=0x7f126000fb60, com_data=0x7f12f81a7bd0, command=COM_FIELD_LIST) at /home/jlong/data/Workspace/mysql814/sql/sql_parse.cc:1883
#10 0x00000000030084ba in do_command (thd=0x7f126000fb60) at /home/jlong/data/Workspace/mysql814/sql/sql_parse.cc:1263
#11 0x00000000031ad008 in handle_connection (arg=0x8b97020) at /home/jlong/data/Workspace/mysql814/sql/conn_handler/connection_handler_per_thread.cc:305
#12 0x0000000004b634e7 in pfs_spawn_thread (arg=0x8bab6b0) at /home/jlong/data/Workspace/mysql814/storage/perfschema/pfs.cc:2836
#13 0x00007f13289eee25 in start_thread () from /lib64/libpthread.so.0
#14 0x00007f1326e5435d in clone () from /lib64/libc.so.6

command \q will not free this object, until drop table.
Drop table:
(gdb) bt
#0  ha_innobase::~ha_innobase (this=0x7f12604293d8, __in_chrg=<optimized out>) at /home/jlong/data/Workspace/mysql814/storage/innobase/handler/ha_innodb.cc:2717
#1  0x0000000002edd153 in destroy<handler> (ptr=0x7f12604293d8) at /home/jlong/data/Workspace/mysql814/include/my_alloc.h:374
#2  0x000000000314e088 in closefrm (table=0x7f12603645a0, free_share=true) at /home/jlong/data/Workspace/mysql814/sql/table.cc:3179
#3  0x0000000002f58a64 in intern_close_table (table=0x7f12603645a0) at /home/jlong/data/Workspace/mysql814/sql/sql_base.cc:1101
#4  0x0000000003160e52 in Table_cache_manager::free_table (this=0x6da5560 <table_cache_manager>, thd=0x7f126000fb60, remove_type=TDC_RT_REMOVE_ALL, share=0x7f12603f9248) at /home/jlong/data/Workspace/mysql814/sql/table_cache.cc:312
#5  0x0000000002f6c0fd in <lambda(std::unordered_map<std::basic_string<char>, std::unique_ptr<TABLE_SHARE, Table_share_deleter>, std::hash<std::basic_string<char> >, std::equal_to<std::basic_string<char> >, Malloc_allocator<std::pair<const std::basic_string<char>, std::unique_ptr<TABLE_SHARE, Table_share_deleter> > > >::iterator)>::operator()(std::unordered_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<TABLE_SHARE, Table_share_deleter>, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Malloc_allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<TABLE_SHARE, Table_share_deleter> > > >::iterator) const (__closure=0x7f12f81a3a10, it=...) at /home/jlong/data/Workspace/mysql814/sql/sql_base.cc:9644
#6  0x0000000002f6c392 in tdc_remove_table (thd=0x7f126000fb60, remove_type=TDC_RT_REMOVE_ALL, db=0x7f12606baa28 "mysql", table_name=0x7f1260628ac8 "example", has_lock=false) at /home/jlong/data/Workspace/mysql814/sql/sql_base.cc:9656
#7  0x00000000030a7438 in drop_base_table (thd=0x7f126000fb60, drop_ctx=..., table=0x7f12606d3388, atomic=true, post_ddl_htons=0x7f12f81a5460, fk_invalidator=0x7f12f81a5490, safe_to_release_mdl=0x7f12f81a5060)
    at /home/jlong/data/Workspace/mysql814/sql/sql_table.cc:2695
#8  0x00000000030a8646 in mysql_rm_table_no_locks (thd=0x7f126000fb60, tables=0x7f12606d3388, if_exists=false, drop_temporary=false, drop_database=false, dropped_non_atomic_flag=0x7f12f81a553f, post_ddl_htons=0x7f12f81a5460, fk_invalidator=0x7f12f81a5490, 
    safe_to_release_mdl=0x7f12f81a5540) at /home/jlong/data/Workspace/mysql814/sql/sql_table.cc:3066
#9  0x00000000030a4837 in mysql_rm_table (thd=0x7f126000fb60, tables=0x7f12606d3388, if_exists=false, drop_temporary=false) at /home/jlong/data/Workspace/mysql814/sql/sql_table.cc:1470
#10 0x000000000300e8a5 in mysql_execute_command (thd=0x7f126000fb60, first_level=true) at /home/jlong/data/Workspace/mysql814/sql/sql_parse.cc:3386
#11 0x00000000030141fc in mysql_parse (thd=0x7f126000fb60, parser_state=0x7f12f81a6b60, force_primary_storage_engine=false) at /home/jlong/data/Workspace/mysql814/sql/sql_parse.cc:5105
#12 0x0000000003009ef6 in dispatch_command (thd=0x7f126000fb60, com_data=0x7f12f81a7bd0, command=COM_QUERY) at /home/jlong/data/Workspace/mysql814/sql/sql_parse.cc:1715
#13 0x00000000030084ba in do_command (thd=0x7f126000fb60) at /home/jlong/data/Workspace/mysql814/sql/sql_parse.cc:1263
#14 0x00000000031ad008 in handle_connection (arg=0x8b97020) at /home/jlong/data/Workspace/mysql814/sql/conn_handler/connection_handler_per_thread.cc:305
#15 0x0000000004b634e7 in pfs_spawn_thread (arg=0x8bab6b0) at /home/jlong/data/Workspace/mysql814/storage/perfschema/pfs.cc:2836
#16 0x00007f13289eee25 in start_thread () from /lib64/libpthread.so.0
#17 0x00007f1326e5435d in clone () from /lib64/libc.so.6
[28 Feb 2019 10:14] long jian
I catch it thought open_table_from_share's parameter alias=0x7f1260855348 "example".
[28 Feb 2019 14:05] MySQL Verification Team
Hi,

Thank you for your stacktraces.

This shows clearly what is happening here and this is not a bug.

Simply, when each new table handle is open (and for each thread), table handle is added into the table cache. Hence, it will be freed when that cache is flushed or when LRU algorithm decides or when server is shutdown or when table is dropped.

Not a bug.