Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-16711

Crash in Field_blob::store() while reading statistics for the small InnoDB table

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • 10.2.14, 10.1(EOL), 10.2(EOL), 10.3(EOL)
    • 10.1.35, 10.2.17, 10.3.9
    • Optimizer
    • None

    Description

      The following crash happened recently:

      180707 3:37:19 [ERROR] mysqld got signal 11 ;
      This could be because you hit a bug. It is also possible that this binary
      or one of the libraries it was linked against is corrupt, improperly built,
      or misconfigured. This error can also be caused by malfunctioning hardware.
       
      To report this bug, see https://mariadb.com/kb/en/reporting-bugs
       
      We will try our best to scrape up some info that will hopefully help
      diagnose the problem, but since we have already crashed,
      something is definitely wrong and this may fail.
       
      Server version: 10.2.14-MariaDB-log
      key_buffer_size=67108864
      read_buffer_size=131072
      max_used_connections=7
      max_threads=302
      thread_count=13
      It is possible that mysqld could use up to
      key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 729244 K bytes of memory
      Hope that's ok; if not, decrease some variables in the equation.
       
      Thread pointer: 0x7f9ac9c4f7a8
      Attempting backtrace. You can use the following information to find out
      where mysqld died. If you see no messages after this, something went
      terribly wrong...
      stack_bottom = 0x7fa138048d80 thread_stack 0x40000
      mysys/stacktrace.c:267(my_print_stacktrace)[0x55dcffa848bd]
      sql/signal_handler.cc:168(handle_fatal_signal)[0x55dcff4b80f2]
      sigaction.c:0(__restore_rt)[0x7fa13d5e95e0]
      sql/field.cc:7927(Field_blob::store(char const*, unsigned int, charset_info_st const*))[0x55dcff4a16f7]
      sql/sql_statistics.cc:1152(Column_stat::get_stat_values())[0x55dcff2e4e21]
      sql/sql_statistics.cc:2986(read_statistics_for_table)[0x55dcff2e0545]
      sql/sql_statistics.cc:3240(read_statistics_for_tables_if_needed(THD*, TABLE_LIST*))[0x55dcff2e10a7]
      sql/sql_base.cc:4855(open_and_lock_tables(THD*, DDL_options_st const&, TABLE_LIST*, bool, unsigned int, Prelocking_strategy*))[0x55dcff1dbdb2]
      sql/sql_base.h:498(open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int))[0x55dcff1a5f19]
      sql/sql_parse.cc:6432(execute_sqlcom_select)[0x55dcff24ad24]
      sql/sql_parse.cc:3736(mysql_execute_command(THD*))[0x55dcff2428e1]
      sql/sql_parse.cc:7978(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x55dcff24e48c]
      sql/sql_parse.cc:1837(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x55dcff23de2d]
      sql/sql_parse.cc:1383(do_command(THD*))[0x55dcff23ca79]
      sql/sql_connect.cc:1335(do_handle_one_connection(CONNECT*))[0x55dcff365860]
      sql/sql_connect.cc:1242(handle_one_connection)[0x55dcff3655c0]
      pthread_create.c:0(start_thread)[0x7fa13d5e1e25]
      /lib64/libc.so.6(clone+0x6d)[0x7fa13bbb934d]
       
      Trying to get some variables.
      Some pointers may be invalid and cause the dump to abort.
      Query (0x7f9ac9a69790): SELECT MAX(T_ID) FROM T
      Connection ID (thread ID): 5660
      Status: NOT_KILLED
      ...
      

      In the above T is a small InnoDB table and T_ID is its primary key column.

      Attachments

        Issue Links

          Activity

            --source include/have_innodb.inc
             
            SET use_stat_tables= PREFERABLY;
             
            CREATE TABLE t1 (pk INT PRIMARY KEY, t CHAR(60)) ENGINE=InnoDB;
            INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
            ANALYZE TABLE t1;
            CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB;
            SELECT MAX(pk) FROM t1;
             
            # Cleanup
            DROP TABLE t1;
            

            Note: MAX() is not necessary, it fails with just SELECT pk, I'm just keeping it close to the original report.

            10.1 1d10c9afe0f

            #3  <signal handler called>
            #4  0x000055c30a67642f in Field_blob::store (this=0x7ff3d4f2e068, from=0x7ff3c84c86cd "bar", length=3, cs=0x55c30b582f80 <my_charset_bin>) at /data/src/10.1/sql/field.cc:7945
            #5  0x000055c30a4fee18 in Column_stat::get_stat_values (this=0x7ff3e05c2130) at /data/src/10.1/sql/sql_statistics.cc:1151
            #6  0x000055c30a4fa3dd in read_statistics_for_table (thd=0x7ff3d4fc7070, table=0x7ff3c8481c70, stat_tables=0x7ff3e05c22f0) at /data/src/10.1/sql/sql_statistics.cc:2987
            #7  0x000055c30a4fafe5 in read_statistics_for_tables_if_needed (thd=0x7ff3d4fc7070, tables=0x7ff3c84433d8) at /data/src/10.1/sql/sql_statistics.cc:3242
            #8  0x000055c30a3ee6a9 in open_and_lock_tables (thd=0x7ff3d4fc7070, options=..., tables=0x7ff3c84433d8, derived=true, flags=0, prelocking_strategy=0x7ff3e05c3590) at /data/src/10.1/sql/sql_base.cc:5294
            #9  0x000055c30a3e1f73 in open_and_lock_tables (thd=0x7ff3d4fc7070, tables=0x7ff3c84433d8, derived=true, flags=0) at /data/src/10.1/sql/sql_base.h:541
            #10 0x000055c30a45bbff in execute_sqlcom_select (thd=0x7ff3d4fc7070, all_tables=0x7ff3c84433d8) at /data/src/10.1/sql/sql_parse.cc:5865
            #11 0x000055c30a452534 in mysql_execute_command (thd=0x7ff3d4fc7070) at /data/src/10.1/sql/sql_parse.cc:2990
            #12 0x000055c30a45fbcb in mysql_parse (thd=0x7ff3d4fc7070, rawbuf=0x7ff3c8443088 "SELECT MAX(pk) FROM t1", length=22, parser_state=0x7ff3e05c45e0) at /data/src/10.1/sql/sql_parse.cc:7449
            #13 0x000055c30a44e605 in dispatch_command (command=COM_QUERY, thd=0x7ff3d4fc7070, packet=0x7ff3d6ec3071 "SELECT MAX(pk) FROM t1", packet_length=22) at /data/src/10.1/sql/sql_parse.cc:1492
            #14 0x000055c30a44d38a in do_command (thd=0x7ff3d4fc7070) at /data/src/10.1/sql/sql_parse.cc:1121
            #15 0x000055c30a58722d in do_handle_one_connection (thd_arg=0x7ff3d4fc7070) at /data/src/10.1/sql/sql_connect.cc:1330
            #16 0x000055c30a586f91 in handle_one_connection (arg=0x7ff3d4fc7070) at /data/src/10.1/sql/sql_connect.cc:1242
            #17 0x000055c30a944446 in pfs_spawn_thread (arg=0x7ff3d93f2670) at /data/src/10.1/storage/perfschema/pfs.cc:1861
            #18 0x00007ff3e0254494 in start_thread (arg=0x7ff3e05c5b00) at pthread_create.c:333
            #19 0x00007ff3de60d93f in clone () from /lib/x86_64-linux-gnu/libc.so.6
            

            10.0 doesn't crash for me (and no ASAN errors), but valgrind produces "loss record" warnings:

            10.0 a2c0376e0

            ***Warnings generated in error logs during shutdown after running tests: bug.mdev16711a
             
            Warning:    8 bytes lost at 0x16bab6f0, allocated by T@0 at 0x6edcfb, 0x5a61f3, 0x823c24, 0x6ebb3d, 0x6e7589, 0x6e804d, 0x5f107b, 0x5e5331
            Warning:    8 bytes lost at 0x16bab630, allocated by T@0 at 0x6edcfb, 0x5a61f3, 0x823c24, 0x6eba93, 0x6e7589, 0x6e804d, 0x5f107b, 0x5e5331
            ==12166== 124 bytes in 1 blocks are still reachable in loss record 5 of 9
            ==12166==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
            ==12166==    by 0xE35118: sf_malloc (safemalloc.c:115)
            ==12166==    by 0xE240DA: my_malloc (my_malloc.c:100)
            ==12166==    by 0x6EDCFA: String::real_alloc(unsigned int) (sql_string.cc:46)
            ==12166==    by 0x5A61F2: String::alloc(unsigned int) (sql_string.h:277)
            ==12166==    by 0x823C23: Field_blob::store(char const*, unsigned int, charset_info_st const*) (field.cc:7403)
            ==12166==    by 0x6EBA92: Column_stat::get_stat_values() (sql_statistics.cc:1009)
            ==12166==    by 0x6E7588: read_statistics_for_table(THD*, TABLE*, TABLE_LIST*) (sql_statistics.cc:2848)
            ==12166==    by 0x6E804C: read_statistics_for_tables_if_needed(THD*, TABLE_LIST*) (sql_statistics.cc:3103)
            ==12166==    by 0x5F107A: open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int, Prelocking_strategy*) (sql_base.cc:5255)
            ==12166==    by 0x5E5330: open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int) (sql_base.h:496)
            ==12166==    by 0x654CE5: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:5243)
            ==12166==    by 0x64D4CE: mysql_execute_command(THD*) (sql_parse.cc:2554)
            ==12166==    by 0x657DD5: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:6634)
            ==12166==    by 0x64A6F5: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1297)
            ==12166==    by 0x6499F5: do_command(THD*) (sql_parse.cc:1000)
            ==12166== 124 bytes in 1 blocks are still reachable in loss record 6 of 9
            ==12166==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
            ==12166==    by 0xE35118: sf_malloc (safemalloc.c:115)
            ==12166==    by 0xE240DA: my_malloc (my_malloc.c:100)
            ==12166==    by 0x6EDCFA: String::real_alloc(unsigned int) (sql_string.cc:46)
            ==12166==    by 0x5A61F2: String::alloc(unsigned int) (sql_string.h:277)
            ==12166==    by 0x823C23: Field_blob::store(char const*, unsigned int, charset_info_st const*) (field.cc:7403)
            ==12166==    by 0x6EBB3C: Column_stat::get_stat_values() (sql_statistics.cc:1015)
            ==12166==    by 0x6E7588: read_statistics_for_table(THD*, TABLE*, TABLE_LIST*) (sql_statistics.cc:2848)
            ==12166==    by 0x6E804C: read_statistics_for_tables_if_needed(THD*, TABLE_LIST*) (sql_statistics.cc:3103)
            ==12166==    by 0x5F107A: open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int, Prelocking_strategy*) (sql_base.cc:5255)
            ==12166==    by 0x5E5330: open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int) (sql_base.h:496)
            ==12166==    by 0x654CE5: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:5243)
            ==12166==    by 0x64D4CE: mysql_execute_command(THD*) (sql_parse.cc:2554)
            ==12166==    by 0x657DD5: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:6634)
            ==12166==    by 0x64A6F5: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1297)
            ==12166==    by 0x6499F5: do_command(THD*) (sql_parse.cc:1000)
            

            elenst Elena Stepanova added a comment - --source include/have_innodb.inc   SET use_stat_tables= PREFERABLY;   CREATE TABLE t1 (pk INT PRIMARY KEY , t CHAR (60)) ENGINE=InnoDB; INSERT INTO t1 VALUES (1, 'foo' ),(2, 'bar' ); ANALYZE TABLE t1; CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY , t TEXT) ENGINE=InnoDB; SELECT MAX (pk) FROM t1;   # Cleanup DROP TABLE t1; Note: MAX() is not necessary, it fails with just SELECT pk , I'm just keeping it close to the original report. 10.1 1d10c9afe0f #3 <signal handler called> #4 0x000055c30a67642f in Field_blob::store (this=0x7ff3d4f2e068, from=0x7ff3c84c86cd "bar", length=3, cs=0x55c30b582f80 <my_charset_bin>) at /data/src/10.1/sql/field.cc:7945 #5 0x000055c30a4fee18 in Column_stat::get_stat_values (this=0x7ff3e05c2130) at /data/src/10.1/sql/sql_statistics.cc:1151 #6 0x000055c30a4fa3dd in read_statistics_for_table (thd=0x7ff3d4fc7070, table=0x7ff3c8481c70, stat_tables=0x7ff3e05c22f0) at /data/src/10.1/sql/sql_statistics.cc:2987 #7 0x000055c30a4fafe5 in read_statistics_for_tables_if_needed (thd=0x7ff3d4fc7070, tables=0x7ff3c84433d8) at /data/src/10.1/sql/sql_statistics.cc:3242 #8 0x000055c30a3ee6a9 in open_and_lock_tables (thd=0x7ff3d4fc7070, options=..., tables=0x7ff3c84433d8, derived=true, flags=0, prelocking_strategy=0x7ff3e05c3590) at /data/src/10.1/sql/sql_base.cc:5294 #9 0x000055c30a3e1f73 in open_and_lock_tables (thd=0x7ff3d4fc7070, tables=0x7ff3c84433d8, derived=true, flags=0) at /data/src/10.1/sql/sql_base.h:541 #10 0x000055c30a45bbff in execute_sqlcom_select (thd=0x7ff3d4fc7070, all_tables=0x7ff3c84433d8) at /data/src/10.1/sql/sql_parse.cc:5865 #11 0x000055c30a452534 in mysql_execute_command (thd=0x7ff3d4fc7070) at /data/src/10.1/sql/sql_parse.cc:2990 #12 0x000055c30a45fbcb in mysql_parse (thd=0x7ff3d4fc7070, rawbuf=0x7ff3c8443088 "SELECT MAX(pk) FROM t1", length=22, parser_state=0x7ff3e05c45e0) at /data/src/10.1/sql/sql_parse.cc:7449 #13 0x000055c30a44e605 in dispatch_command (command=COM_QUERY, thd=0x7ff3d4fc7070, packet=0x7ff3d6ec3071 "SELECT MAX(pk) FROM t1", packet_length=22) at /data/src/10.1/sql/sql_parse.cc:1492 #14 0x000055c30a44d38a in do_command (thd=0x7ff3d4fc7070) at /data/src/10.1/sql/sql_parse.cc:1121 #15 0x000055c30a58722d in do_handle_one_connection (thd_arg=0x7ff3d4fc7070) at /data/src/10.1/sql/sql_connect.cc:1330 #16 0x000055c30a586f91 in handle_one_connection (arg=0x7ff3d4fc7070) at /data/src/10.1/sql/sql_connect.cc:1242 #17 0x000055c30a944446 in pfs_spawn_thread (arg=0x7ff3d93f2670) at /data/src/10.1/storage/perfschema/pfs.cc:1861 #18 0x00007ff3e0254494 in start_thread (arg=0x7ff3e05c5b00) at pthread_create.c:333 #19 0x00007ff3de60d93f in clone () from /lib/x86_64-linux-gnu/libc.so.6 10.0 doesn't crash for me (and no ASAN errors), but valgrind produces "loss record" warnings: 10.0 a2c0376e0 ***Warnings generated in error logs during shutdown after running tests: bug.mdev16711a   Warning: 8 bytes lost at 0x16bab6f0, allocated by T@0 at 0x6edcfb, 0x5a61f3, 0x823c24, 0x6ebb3d, 0x6e7589, 0x6e804d, 0x5f107b, 0x5e5331 Warning: 8 bytes lost at 0x16bab630, allocated by T@0 at 0x6edcfb, 0x5a61f3, 0x823c24, 0x6eba93, 0x6e7589, 0x6e804d, 0x5f107b, 0x5e5331 ==12166== 124 bytes in 1 blocks are still reachable in loss record 5 of 9 ==12166== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==12166== by 0xE35118: sf_malloc (safemalloc.c:115) ==12166== by 0xE240DA: my_malloc (my_malloc.c:100) ==12166== by 0x6EDCFA: String::real_alloc(unsigned int) (sql_string.cc:46) ==12166== by 0x5A61F2: String::alloc(unsigned int) (sql_string.h:277) ==12166== by 0x823C23: Field_blob::store(char const*, unsigned int, charset_info_st const*) (field.cc:7403) ==12166== by 0x6EBA92: Column_stat::get_stat_values() (sql_statistics.cc:1009) ==12166== by 0x6E7588: read_statistics_for_table(THD*, TABLE*, TABLE_LIST*) (sql_statistics.cc:2848) ==12166== by 0x6E804C: read_statistics_for_tables_if_needed(THD*, TABLE_LIST*) (sql_statistics.cc:3103) ==12166== by 0x5F107A: open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int, Prelocking_strategy*) (sql_base.cc:5255) ==12166== by 0x5E5330: open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int) (sql_base.h:496) ==12166== by 0x654CE5: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:5243) ==12166== by 0x64D4CE: mysql_execute_command(THD*) (sql_parse.cc:2554) ==12166== by 0x657DD5: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:6634) ==12166== by 0x64A6F5: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1297) ==12166== by 0x6499F5: do_command(THD*) (sql_parse.cc:1000) ==12166== 124 bytes in 1 blocks are still reachable in loss record 6 of 9 ==12166== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==12166== by 0xE35118: sf_malloc (safemalloc.c:115) ==12166== by 0xE240DA: my_malloc (my_malloc.c:100) ==12166== by 0x6EDCFA: String::real_alloc(unsigned int) (sql_string.cc:46) ==12166== by 0x5A61F2: String::alloc(unsigned int) (sql_string.h:277) ==12166== by 0x823C23: Field_blob::store(char const*, unsigned int, charset_info_st const*) (field.cc:7403) ==12166== by 0x6EBB3C: Column_stat::get_stat_values() (sql_statistics.cc:1015) ==12166== by 0x6E7588: read_statistics_for_table(THD*, TABLE*, TABLE_LIST*) (sql_statistics.cc:2848) ==12166== by 0x6E804C: read_statistics_for_tables_if_needed(THD*, TABLE_LIST*) (sql_statistics.cc:3103) ==12166== by 0x5F107A: open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int, Prelocking_strategy*) (sql_base.cc:5255) ==12166== by 0x5E5330: open_and_lock_tables(THD*, TABLE_LIST*, bool, unsigned int) (sql_base.h:496) ==12166== by 0x654CE5: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:5243) ==12166== by 0x64D4CE: mysql_execute_command(THD*) (sql_parse.cc:2554) ==12166== by 0x657DD5: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:6634) ==12166== by 0x64A6F5: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1297) ==12166== by 0x6499F5: do_command(THD*) (sql_parse.cc:1000)
            igor Igor Babaev (Inactive) added a comment - - edited

            Here's what happens when running the reported test case.
            After the command

            ANALYZE TABLE t1;
            

            we have the following statistics on the columns of the table t1

            MariaDB [test]> select * from mysql.column_stats;
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            | db_name | table_name | column_name | min_value | max_value | nulls_ratio | avg_length | avg_frequency | hist_size | hist_type | histogram |
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            | test    | t1         | t           | bar       | foo       |      0.0000 |     3.0000 |        1.0000 |         0 | NULL      | NULL      |
            | test    | t1         | pk          | 1         | 2         |      0.0000 |     4.0000 |        1.0000 |         0 | NULL      | NULL      |
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            

            After having run the statement:

            CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB;
            

            we still have

            MariaDB [test]> select * from mysql.column_stats;
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            | db_name | table_name | column_name | min_value | max_value | nulls_ratio | avg_length | avg_frequency | hist_size | hist_type | histogram |
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            | test    | t1         | t           | bar       | foo       |      0.0000 |     3.0000 |        1.0000 |         0 | NULL      | NULL      |
            | test    | t1         | pk          | 1         | 2         |      0.0000 |     4.0000 |        1.0000 |         0 | NULL      | NULL      |
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            

            thou table t1 is now empty

            MariaDB [test]> SET use_stat_tables= default;
            Query OK, 0 rows affected (0.00 sec)
             
            MariaDB [test]> select * from t1;
            Empty set (0.00 sec)
            

            This is already a bug as the command CREATE OR REPLACE TABLE t1 should have deleted the statistics on table t1.
            Yet this bug could not cause the crash that we observe when running any select statement over t1.
            The crash happens when we try to read statistics on min/max values for the column t from t1.
            The crash is caused by the following code in the function Field_blob::store introduced in the patch 6c414fcf89510215d6d3466eb9992d444eadae89.

            if (table->blob_storage)
            

            The fact is that when we read statistics for min/max values for any column of table T with use Field objects shared by all table instances with the name T as statistical data is the same for all of them. So the value of the 'table' field does not make sense for these objects and is set to 0.
            The patch did not take this into account.

            The crash may happen only in this rare scenario that we see in the reported test case. If we execute the equivalent sequence

            DROP TABLE t1;
            CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB;
            

            instead of

            CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB;
            

            no crash happens. More than this: the statistics on t1 is updated.

            MariaDB [test]> DROP TABLE t1;
            Query OK, 0 rows affected (0.01 sec)
             
            MariaDB [test]> CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB;
            Query OK, 0 rows affected (0.02 sec)
             
            MariaDB [test]> SELECT MAX(pk) FROM t1;
            +---------+
            | MAX(pk) |
            +---------+
            |    NULL |
            +---------+
            1 row in set (0.00 sec)
             
            MariaDB [test]> select * from mysql.column_stats;
            

            Now if we even add some rows to t1 and run ANALYZE TABLE for it we still have no problems because statistical data for BLOB columns is not collected.

            MariaDB [test]> INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
            Query OK, 2 rows affected (0.01 sec)
            Records: 2  Duplicates: 0  Warnings: 0
             
            MariaDB [test]> ANALYZE TABLE t1;
            +---------+---------+----------+----------------------------------------------------------------+
            | Table   | Op      | Msg_type | Msg_text                                                       |
            +---------+---------+----------+----------------------------------------------------------------+
            | test.t1 | analyze | status   | Engine-independent statistics collected                        |
            | test.t1 | analyze | Warning  | Engine-independent statistics are not collected for column 't' |
            | test.t1 | analyze | status   | OK                                                             |
            +---------+---------+----------+----------------------------------------------------------------+
            3 rows in set (0.01 sec)
             
            MariaDB [test]> SELECT MAX(pk) FROM t1;
            +---------+
            | MAX(pk) |
            +---------+
            |       2 |
            +---------+
            1 row in set (4.87 sec)
             
            MariaDB [test]> select * from mysql.column_stats;
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            | db_name | table_name | column_name | min_value | max_value | nulls_ratio | avg_length | avg_frequency | hist_size | hist_type | histogram |
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            | test    | t1         | pk          | 1         | 2         |      0.0000 |     4.0000 |        1.0000 |         0 | NULL      | NULL      |
            +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+
            1 row in set (0.00 sec)
            

            We do not see any crash in 10.0 because the patch 6c414fcf89510215d6d3466eb9992d444eadae89 was applied only starting from 10.1 though the bug with not deleted statistics of course exists in 10.0 as well.

            igor Igor Babaev (Inactive) added a comment - - edited Here's what happens when running the reported test case. After the command ANALYZE TABLE t1; we have the following statistics on the columns of the table t1 MariaDB [test]> select * from mysql.column_stats; +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ | db_name | table_name | column_name | min_value | max_value | nulls_ratio | avg_length | avg_frequency | hist_size | hist_type | histogram | +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ | test | t1 | t | bar | foo | 0.0000 | 3.0000 | 1.0000 | 0 | NULL | NULL | | test | t1 | pk | 1 | 2 | 0.0000 | 4.0000 | 1.0000 | 0 | NULL | NULL | +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ After having run the statement: CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB; we still have MariaDB [test]> select * from mysql.column_stats; +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ | db_name | table_name | column_name | min_value | max_value | nulls_ratio | avg_length | avg_frequency | hist_size | hist_type | histogram | +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ | test | t1 | t | bar | foo | 0.0000 | 3.0000 | 1.0000 | 0 | NULL | NULL | | test | t1 | pk | 1 | 2 | 0.0000 | 4.0000 | 1.0000 | 0 | NULL | NULL | +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ thou table t1 is now empty MariaDB [test]> SET use_stat_tables= default; Query OK, 0 rows affected (0.00 sec)   MariaDB [test]> select * from t1; Empty set (0.00 sec) This is already a bug as the command CREATE OR REPLACE TABLE t1 should have deleted the statistics on table t1. Yet this bug could not cause the crash that we observe when running any select statement over t1. The crash happens when we try to read statistics on min/max values for the column t from t1. The crash is caused by the following code in the function Field_blob::store introduced in the patch 6c414fcf89510215d6d3466eb9992d444eadae89. if (table->blob_storage) The fact is that when we read statistics for min/max values for any column of table T with use Field objects shared by all table instances with the name T as statistical data is the same for all of them. So the value of the 'table' field does not make sense for these objects and is set to 0. The patch did not take this into account. The crash may happen only in this rare scenario that we see in the reported test case. If we execute the equivalent sequence DROP TABLE t1; CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB; instead of CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB; no crash happens. More than this: the statistics on t1 is updated. MariaDB [test]> DROP TABLE t1; Query OK, 0 rows affected (0.01 sec)   MariaDB [test]> CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB; Query OK, 0 rows affected (0.02 sec)   MariaDB [test]> SELECT MAX(pk) FROM t1; +---------+ | MAX(pk) | +---------+ | NULL | +---------+ 1 row in set (0.00 sec)   MariaDB [test]> select * from mysql.column_stats; Now if we even add some rows to t1 and run ANALYZE TABLE for it we still have no problems because statistical data for BLOB columns is not collected. MariaDB [test]> INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0   MariaDB [test]> ANALYZE TABLE t1; +---------+---------+----------+----------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +---------+---------+----------+----------------------------------------------------------------+ | test.t1 | analyze | status | Engine-independent statistics collected | | test.t1 | analyze | Warning | Engine-independent statistics are not collected for column 't' | | test.t1 | analyze | status | OK | +---------+---------+----------+----------------------------------------------------------------+ 3 rows in set (0.01 sec)   MariaDB [test]> SELECT MAX(pk) FROM t1; +---------+ | MAX(pk) | +---------+ | 2 | +---------+ 1 row in set (4.87 sec)   MariaDB [test]> select * from mysql.column_stats; +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ | db_name | table_name | column_name | min_value | max_value | nulls_ratio | avg_length | avg_frequency | hist_size | hist_type | histogram | +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ | test | t1 | pk | 1 | 2 | 0.0000 | 4.0000 | 1.0000 | 0 | NULL | NULL | +---------+------------+-------------+-----------+-----------+-------------+------------+---------------+-----------+-----------+-----------+ 1 row in set (0.00 sec) We do not see any crash in 10.0 because the patch 6c414fcf89510215d6d3466eb9992d444eadae89 was applied only starting from 10.1 though the bug with not deleted statistics of course exists in 10.0 as well.

            A fix for this bug was pushed into 10.1

            igor Igor Babaev (Inactive) added a comment - A fix for this bug was pushed into 10.1

            People

              igor Igor Babaev (Inactive)
              valerii Valerii Kravchuk
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.