Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-3841 LevelDB storage engine
  3. MDEV-4094

LevelDB: Wrong result on SELECT and ER_KEY_NOT_FOUND on DELETE with search by NULL-able secondary key after updating PK

    Details

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

      Description

      CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, b CHAR(1), KEY(a)) ENGINE=LevelDB;
      INSERT INTO t1 VALUES (1,8,'g'),(2,9,'x');
      UPDATE t1 SET pk = 10 WHERE a = 8;
      REPLACE INTO t1 ( a ) VALUES ( 8 );
      Warnings:
      Warning	1364	Field 'pk' doesn't have a default value
      REPLACE INTO t1 ( b ) VALUES ( 'y' );
      Warnings:
      Warning	1364	Field 'pk' doesn't have a default value
      SELECT * FROM t1;
      pk	a	b
      0	NULL	y
      2	9	x
      10	8	g
      EXPLAIN EXTENDED
      SELECT * FROM t1 WHERE a = 8;
      id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
      1	SIMPLE	t1	ref	a	a	5	const	10	100.00	NULL
      Warnings:
      Note	1003	/* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a` = 8)
      SELECT * FROM t1 WHERE a = 8;
      pk	a	b
      0	NULL	y
      EXPLAIN EXTENDED
      DELETE FROM t1 WHERE a = 8;
      id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
      1	SIMPLE	t1	range	PRIMARY,a	a	5	NULL	10	100.00	Using where
      
      query 'DELETE FROM t1 WHERE a = 8' failed: 1032: Can't find record in 't1'
      

      Test case:

      CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, b CHAR(1), KEY(a)) ENGINE=LevelDB;
      INSERT INTO t1 VALUES (1,8,'g'),(2,9,'x');
      UPDATE t1 SET pk = 10 WHERE a = 8;
      REPLACE INTO t1 ( a ) VALUES ( 8 );
      REPLACE INTO t1 ( b ) VALUES ( 'y' );
      SELECT * FROM t1 WHERE a = 8;
      DELETE FROM t1 WHERE a = 8;
      
      revision-id: psergey@askmonty.org-20130125200959-a7gq7phbaiajqs12
      revno: 4519
      branch-nick: mysql-5.6-leveldb
      

        Gliffy Diagrams

          Attachments

            Activity

            Hide
            psergey Sergei Petrunia added a comment -

            The problem is casused by this statement:

            UPDATE t1 SET pk = 10 WHERE a = 8;

            It doesn't delete entries in the secondary index. leveldb contents after the statement:

            "j2.t1\1\0\0\0\0\2" -> "-7\2\0\0\0\9\0\0\0x"
            "j2.t1\1\0\0\0\0\10" -> "-7\10\0\0\0\8\0\0\0g"
            "j2.t1\2\0\1\0\0\0\8\0\0\0\1" -> ""
            "j2.t1\2\0\1\0\0\0\8\0\0\0\10" -> ""
            "j2.t1\2\0\1\0\0\0\9\0\0\0\2" -> ""

            Note

            • two records, but three index entries
            • two secondary index entries with a=8.

            This happens because this function from sql/key.cc:

            void key_copy(uchar *to_key, uchar *from_record, KEY *key_info,
            uint key_length)

            pretends to accept a parameter 'from_record', while internally it calls

            uint bytes= field->get_key_image(to_key, length, Field::itRAW);

            And 'field' normally points to table->record[0].

            This is why LevelDB SE is trying to delete a wrong entry in the secondary index (which succeeds, because LevelDB's Delete() calls dont fail)

            Show
            psergey Sergei Petrunia added a comment - The problem is casused by this statement: UPDATE t1 SET pk = 10 WHERE a = 8; It doesn't delete entries in the secondary index. leveldb contents after the statement: "j2.t1\1\0\0\0\0\2" -> "-7\2\0\0\0\9\0\0\0x" "j2.t1\1\0\0\0\0\10" -> "-7\10\0\0\0\8\0\0\0g" "j2.t1\2\0\1\0\0\0\8\0\0\0\1" -> "" "j2.t1\2\0\1\0\0\0\8\0\0\0\10" -> "" "j2.t1\2\0\1\0\0\0\9\0\0\0\2" -> "" Note two records, but three index entries two secondary index entries with a=8. This happens because this function from sql/key.cc: void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, uint key_length) pretends to accept a parameter 'from_record', while internally it calls uint bytes= field->get_key_image(to_key, length, Field::itRAW); And 'field' normally points to table->record [0] . This is why LevelDB SE is trying to delete a wrong entry in the secondary index (which succeeds, because LevelDB's Delete() calls dont fail)

              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 - 1 hour, 45 minutes
                  1h 45m