pingcap / tidb

TiDB - the open-source, cloud-native, distributed SQL database designed for modern applications.
https://pingcap.com
Apache License 2.0
37.2k stars 5.84k forks source link

assertion failed in strict assertion level #39618

Closed ChenPeng2013 closed 1 year ago

ChenPeng2013 commented 1 year ago

Bug Report

Please answer these questions before submitting your issue. Thanks!

1. Minimal reproduce step (Required)

use test;
source [test.txt](https://github.com/pingcap/tidb/files/10151218/test.txt)
set tidb_txn_assertion_level=strict;
/* test */ /* t04:047 */ begin;
/* test */ /* t04:048 */ update t2 set c_int = c_int + 5, c_str = null where (c_int, c_str) in ((13, 'hungry tesla'), (8, 'amazing engelbart'), (5, 'laughing ptolemy'));
/* test */ /* t04:049 */ select * from t1 where c_datetime < any (select c_datetime from t2 where c_datetime > '2020-06-08 02:04:16') ; -- flags: QUERY
/* test */ /* t04:050 */ insert into t1 values (7, 'stupefied diffie', '2020-06-16 16:41:42', '2020-05-10 09:48:27', 41.622723, 3.511, 'yellow'), (5, 'friendly mendel', '2020-04-01 06:04:50', '2020-06-09 13:07:08', 79.099412, 0.469, 'blue'), (11, 'strange goldberg', '2020-04-11 06:09:32', '2020-04-09 01:37:19', 38.769640, 1.940, 'yellow') on duplicate key update c_int = c_int + 1, c_str = concat(c_int, ':', c_str);
/* test */ /* t04:051 */ (select  * from t1, t2 where t2.c_int is null ) union distinct (select /*+ INL_MERGE_JOIN(t1,t2) */  * from t1 left join t2 on t1.c_int = t2.c_int and t1.c_enum >= t2.c_enum ); -- flags: QUERY
/* test */ /* t04:052 */ delete  t1, t2 from t1, t2 where t1.c_enum in ('blue', 'yellow', 'purple');
/* test */ /* t04:053 */ select * from t1 where c_str <= all (select c_str from t2 where t1.c_double > t2.c_double or t1.c_int = t2.c_int and t1.c_enum = t2.c_enum and t1.c_enum < t2.c_enum) ; -- flags: QUERY
/* test */ /* t04:054 */ select (select t2.c_str from t2 where t1.c_int = t2.c_int and t1.c_str != t2.c_str order by t2.c_str limit 1 ) x from t1 /* force-unordered */; -- flags: QUERY
/* test */ /* t04:055 */ (select /*+ MERGE_JOIN(t1,t2) */  * from t1 left join t2 on t1.c_int = t2.c_int and t1.c_enum != t2.c_enum where t1.c_int = t2.c_int and t1.c_str != t2.c_str or t1.c_enum = t2.c_enum or t1.c_int = t2.c_int and t1.c_enum <> t2.c_enum or t1.c_str = t2.c_str and t2.c_enum in ('purple', 'white', 'white') ) union all (select  * from t1 left join t2 on t1.c_str <= t2.c_str ); -- flags: QUERY
/* test */ /* t04:056 */ (select /*+ INL_HASH_JOIN(t1,t2) */  * from t1, t2 where t1.c_str <= t2.c_str or t1.c_enum = 'blue' for update) union all (select /*+ MERGE_JOIN(t1,t2) */  * from t1, t2 where t2.c_int in (2, 1, 6) ); -- flags: QUERY
/* test */ /* t04:057 */ update t2 partition (p2) set c_int = c_int + 5, c_str = 'happy vaughan' where (c_int, c_str) in ((3, 'frosty mestorf'), (6, 'vigorous booth'), (10, 'gifted haibt'));
/* test */ /* t04:058 */ delete /*+ HASH_JOIN(t1,t2) */  t2 from t1 partition (p1), t2 partition (p1) where t2.c_enum = 'yellow';
/* test */ /* t04:059 */ update /*+ INL_MERGE_JOIN(t1,t2) */  t1 partition (p3), t2 partition (p3) set t2.c_enum = 'yellow' where t1.c_int = t2.c_int and t1.c_str = t2.c_str and (t1.c_str = t2.c_str and t2.c_int = 1);
/* test */ /* t04:060 */ update  t1, t2 set t1.c_timestamp = '2020-04-13 00:51:39' where t1.c_int = t2.c_int and t1.c_str = t2.c_str and (t1.c_str > t2.c_str or t2.c_enum = 'green');
/* test */ /* t04:061 */ update  t1 partition (p1), t2 partition (p1) set t2.c_enum = 'white' where t1.c_int = t2.c_int and t1.c_str = t2.c_str and (t1.c_int < t2.c_int or t2.c_str in ('nostalgic ishizaka', 'happy chatterjee', 'priceless golick'));
/* test */ /* t04:062 */ update /*+ INL_JOIN(t1,t2) */  t1, t2 set t2.c_decimal = 5.021, t1.c_decimal = 9.111 where t1.c_int = t2.c_int and t1.c_str = t2.c_str and (t1.c_str in ('interesting northcutt', 'reverent boyd', 'flamboyant rubin'));
/* test */ /* t04:063 */ delete from t1 partition (p2) where c_int in (9, 12) or c_str in ('serene kapitsa', 'cranky bartik', 'cool mayer', 'hardcore mahavira') order by c_int, c_str, c_double, c_decimal limit 1;
/* test */ /* t04:064 */ select /*+ MERGE_JOIN(t1,t2) */  * from t1, t2 where t1.c_int = t2.c_int and t1.c_str <= t2.c_str for update; -- flags: QUERY
/* test */ /* t04:065 */ update /*+ MERGE_JOIN(t1,t2) */  t1 partition (p2), t2 partition (p2) set t1.c_decimal = 1.250, t1.c_int = 10 where t1.c_int = t2.c_int and t1.c_str = t2.c_str and (t1.c_int = t2.c_int and t1.c_str < t2.c_str);
/* test */ /* t04:066 */ commit;

2. What did you expect to see? (Required)

3. What did you see instead (Required)

MySQL [test]> /* test */ /* t04:066 */ commit;
ERROR 8141 (HY000): assertion failed: key: 74800000000000009c5f6980000000000000040419a6631ea2000000038000000000000002017368617270207074ff6f6c656d79000000fc, assertion: Exist, start_ts: 437838730026811393, existing start ts: 0, existing commit ts: 0

4. What is your TiDB version? (Required)

Release Version: v6.5.0-alpha
Edition: Community
Git Commit Hash: 0b1096eac5a500f8c624f08f384d0194da5386f4
Git Branch: heads/refs/tags/v6.5.0-alpha
UTC Build Time: 2022-12-04 14:34:06
GoVersion: go1.19.3
Race Enabled: false
TiKV Min Version: 6.2.0-alpha
Check Table Before Drop: false
Store: tikv
cfzjywxk commented 1 year ago

@TonsnakeLin @zyguan It's a release test failure, please take a look if it's a correnctness issue.

TonsnakeLin commented 1 year ago

we can simplify the reproducing as follow: use test; source test.txt set tidb_txn_assertion_level=strict; / test / / t04:047 / begin; / test / / t04:052 / delete t1, t2 from t1, t2 where t1.c_enum in ('blue', 'yellow', 'purple'); commit;

after sending pessimsitic lock request for delete operation, the mvcc data is bellow:

image

when committing the trans, the error happened.

cfzjywxk commented 1 year ago

Reproduce step:

source test.txt;
set tidb_txn_assertion_level=strict;
begin;
delete t1, t2 from t1, t2 where t1.c_enum in ('blue');
commit; // assertion failure, the to-be-deleted index key could not be found.

The error is reported because the to-be-delete index key is generated incorrectly for table t2 on the secondary index c_datetime. The row to be deleted is

 c_int | c_str                                    | c_datetime          | c_timestamp         | c_double  | c_decimal | c_enum
 12 | 0x6578636974696E6720626F7964             | NULL                | 2020-03-29 02:27:23 |      NULL |  9.249000 | blue

The value of c_datetime is NULL. However, the generated index key is

/mok 7480000000000000da5f6980000000000000040419a5a6aa7000000003800000000000000c016578636974696e67ff20626f7964000000fc
"7480000000000000da5f6980000000000000040419a5a6aa7000000003800000000000000c016578636974696e67ff20626f7964000000fc"
└─## decode hex key
  └─"t\200\000\000\000\000\000\000\332_i\200\000\000\000\000\000\000\004\004\031\245\246\252p\000\000\000\003\200\000\000\000\000\000\000\014\001exciting\377 boyd\000\000\000\374"
    ├─## table prefix
    │ └─table: 218
    └─## table index key
      ├─table: 218
      ├─index: 4
      └─"\004\031\245\246\252p\000\000\000\003\200\000\000\000\000\000\000\014\001exciting\377 boyd\000\000\000\374"
        └─## decode index values
          ├─kind: Uint64, value: 1848066473059155968  // Incorrect value here.
          ├─kind: Int64, value: 12
          └─kind: Bytes, value: exciting boyd

The incorrect value is wrongly referenced from the table t1 with handle value 18. img_v2_c3e9416b-5103-4417-824d-0b5b07586e9g

In deleteMultiTablesByChunk the input value tblRowMap for the removeRowsInTblRowMap seems to have incorrect row values. After reverting the https://github.com/pingcap/tidb/pull/39489 change, the generated index key is correct and no assertion failure is reported.