Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-4201 LevelDB Storage Engine MS2
  3. MDEV-4301

LevelDB: Assertion `pack_info != __null' fails in LDBSE_KEYDEF::unpack_record

    Details

    • Type: Technical task
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:

      Description

      CREATE TABLE t1 (pk INT PRIMARY KEY, i INT, c CHAR(1), KEY(c,i)) ENGINE=LevelDB;
      INSERT INTO t1 VALUES (1,4,'d'),(2,8,'e');
      SELECT MAX( pk ) FROM t1 WHERE i = 105 AND c = 'h';
      
      mysql-5.6-leveldb/storage/leveldb/ldb_datadic.cc:302: int LDBSE_KEYDEF::unpack_record(TABLE*, uchar*, const leveldb::Slice*, const leveldb::Slice*): Assertion `pack_info != __null' failed.
      mysqld got signal 6 ;
      
      #7  0x00007fc03660d192 in __GI___assert_fail (assertion=0x102c8d9 "pack_info != __null", file=0x102c888 "mysql-5.6-leveldb/storage/leveldb/ldb_datadic.cc", line=302, function=0x102ca80 "int LDBSE_KEYDEF::unpack_record(TABLE*, uchar*, const leveldb::Slice*, const leveldb::Slice*)") at assert.c:103
      #8  0x0000000000b0a58e in LDBSE_KEYDEF::unpack_record (this=0x7fc010015d10, table=0x7fc010015e20, buf=0x7fc0100151b8 "\371\002", packed_key=0x7fc0340a2580, unpack_info=0x7fc0340a2590) at mysql-5.6-leveldb/storage/leveldb/ldb_datadic.cc:302
      #9  0x0000000000b05e72 in ha_leveldb::index_read_map (this=0x7fc010014ec0, buf=0x7fc0100151b8 "\371\002", key=0x7fc0340a2830 "", keypart_map=3, find_flag=HA_READ_PREFIX_LAST_OR_PREV) at mysql-5.6-leveldb/storage/leveldb/ha_leveldb.cc:1415
      #10 0x000000000061a298 in handler::ha_index_read_map (this=0x7fc010014ec0, buf=0x7fc0100151b8 "\371\002", key=0x7fc0340a2830 "", keypart_map=3, find_flag=HA_READ_PREFIX_LAST_OR_PREV) at mysql-5.6-leveldb/sql/handler.cc:2668
      #11 0x000000000092dd7d in get_index_max_value (table=0x7fc010015e20, ref=0x7fc0340a2710, range_fl=3) at mysql-5.6-leveldb/sql/opt_sum.cc:207
      #12 0x000000000092e5e4 in opt_sum_query (thd=0x2787a10, tables=0x7fc010005380, all_fields=..., conds=0x7fc010005f98) at mysql-5.6-leveldb/sql/opt_sum.cc:422
      #13 0x0000000000962b27 in JOIN::optimize (this=0x7fc010006198) at mysql-5.6-leveldb/sql/sql_optimizer.cc:305
      #14 0x00000000007cbb34 in mysql_execute_select (thd=0x2787a10, select_lex=0x278a1f0, free_join=true) at mysql-5.6-leveldb/sql/sql_select.cc:1086
      #15 0x00000000007cbe6a in mysql_select (thd=0x2787a10, tables=0x7fc010005380, wild_num=0, fields=..., conds=0x7fc010005f98, order=0x278a3b8, group=0x278a2f0, having=0x0, select_options=2147748608, result=0x7fc010006170, unit=0x2789bb0, select_lex=0x278a1f0) at mysql-5.6-leveldb/sql/sql_select.cc:1221
      #16 0x00000000007c9fba in handle_select (thd=0x2787a10, result=0x7fc010006170, setup_tables_done_option=0) at mysql-5.6-leveldb/sql/sql_select.cc:110
      #17 0x00000000007a6782 in execute_sqlcom_select (thd=0x2787a10, all_tables=0x7fc010005380) at mysql-5.6-leveldb/sql/sql_parse.cc:4987
      #18 0x000000000079f5f4 in mysql_execute_command (thd=0x2787a10) at mysql-5.6-leveldb/sql/sql_parse.cc:2557
      #19 0x00000000007a8be7 in mysql_parse (thd=0x2787a10, rawbuf=0x7fc010004fd0 "SELECT MAX( pk ) FROM t1 WHERE i = 105 AND c = 'h'", length=50, parser_state=0x7fc0340a5110) at mysql-5.6-leveldb/sql/sql_parse.cc:6117
      #20 0x000000000079c9a3 in dispatch_command (command=COM_QUERY, thd=0x2787a10, packet=0x285af71 "SELECT MAX( pk ) FROM t1 WHERE i = 105 AND c = 'h'", packet_length=50) at mysql-5.6-leveldb/sql/sql_parse.cc:1312
      #21 0x000000000079bb66 in do_command (thd=0x2787a10) at mysql-5.6-leveldb/sql/sql_parse.cc:1036
      #22 0x0000000000766e09 in do_handle_one_connection (thd_arg=0x2787a10) at mysql-5.6-leveldb/sql/sql_connect.cc:969
      #23 0x000000000076682e in handle_one_connection (arg=0x2787a10) at mysql-5.6-leveldb/sql/sql_connect.cc:885
      #24 0x0000000000af6924 in pfs_spawn_thread (arg=0x26dcbf0) at mysql-5.6-leveldb/storage/perfschema/pfs.cc:1853
      #25 0x00007fc0371b6e9a in start_thread (arg=0x7fc0340a6700) at pthread_create.c:308
      #26 0x00007fc0366d1cbd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
      
      revision-id: psergey@askmonty.org-20130319094846-yze9xy3qeb5g6hrc
      revno: 4610
      branch-nick: mysql-5.6-leveldb
      

        Gliffy Diagrams

          Attachments

            Activity

            Hide
            psergey Sergei Petrunia added a comment -

            Analysis:

            The problem is caused by SQL layer attempting to do an index-only (HA_EXTRA_KEYREAD) read through KEY(c,i). The literal meaning of assert is "but there is no way to unpack key tuple to record".

            And really, there is no way, because "c CHAR(1)" uses case-insensitive collation.

            However, Field(pk)->part_of_key = 3, and SQL layer interprets it as "the pk field can be restored from the index".

            It is set here:
            Watchpoint 7: *$a
            Old value =

            {map = 1}

            New value =

            {map = 3}

            table.cc: open_binary_frm():
            /*
            If this field is part of the primary key and all keys contains
            the primary key, then we can use any key to find this column
            */
            if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
            {
            if (field->key_length() == key_part->length &&
            !(field->flags & BLOB_FLAG))
            field->part_of_key= share->keys_in_use; <<<

            Show
            psergey Sergei Petrunia added a comment - Analysis: The problem is caused by SQL layer attempting to do an index-only (HA_EXTRA_KEYREAD) read through KEY(c,i). The literal meaning of assert is "but there is no way to unpack key tuple to record". And really, there is no way, because "c CHAR(1)" uses case-insensitive collation. However, Field(pk)->part_of_key = 3, and SQL layer interprets it as "the pk field can be restored from the index". It is set here: Watchpoint 7: *$a Old value = {map = 1} New value = {map = 3} table.cc: open_binary_frm(): /* If this field is part of the primary key and all keys contains the primary key, then we can use any key to find this column */ if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) { if (field->key_length() == key_part->length && !(field->flags & BLOB_FLAG)) field->part_of_key= share->keys_in_use; <<<
            Hide
            psergey Sergei Petrunia added a comment - - edited

            HA_PRIMARY_KEY_IN_READ_INDEX is a flag that we return from table_flags().

            It is defined as:
            /*
            If we get the primary key columns for free when we do an index read
            (usually, it also implies that HA_PRIMARY_KEY_REQUIRED_FOR_POSITION
            flag is set).
            */
            #define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15)

            The problem with this flag is the same as with index_only: SQL layer calls handler->table_flags() before TABLE_SHARE object is filled. Which means - we can't know if we should return this flag (it depends on types of columns).

            Show
            psergey Sergei Petrunia added a comment - - edited HA_PRIMARY_KEY_IN_READ_INDEX is a flag that we return from table_flags(). It is defined as: /* If we get the primary key columns for free when we do an index read (usually, it also implies that HA_PRIMARY_KEY_REQUIRED_FOR_POSITION flag is set). */ #define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15) The problem with this flag is the same as with index_only: SQL layer calls handler->table_flags() before TABLE_SHARE object is filled. Which means - we can't know if we should return this flag (it depends on types of columns).
            Hide
            psergey Sergei Petrunia added a comment -

            Possible solutions:

            Solution #1

            • fix open_binary_frm() to populate TABLE_SHARE object with information about which columns include which indexes, before making any calls to table_flags() or index_flags().
            • fix LDBSE_KEYDEF::unpack_record() so that it is able to retrieve only PK columns.

            Solution #2:

            • Don;t return HA_PRIMARY_KEY_IN_READ_INDEX from ha_leveldb::table_flags(). (This doesn't disable all index-only scans, does it?)
            Show
            psergey Sergei Petrunia added a comment - Possible solutions: Solution #1 fix open_binary_frm() to populate TABLE_SHARE object with information about which columns include which indexes, before making any calls to table_flags() or index_flags(). fix LDBSE_KEYDEF::unpack_record() so that it is able to retrieve only PK columns. Solution #2: Don;t return HA_PRIMARY_KEY_IN_READ_INDEX from ha_leveldb::table_flags(). (This doesn't disable all index-only scans, does it?)

              People

              • Assignee:
                psergey Sergei Petrunia
                Reporter:
                elenst Elena Stepanova
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 7 hours, 30 minutes
                  7h 30m