Skip to content

[Bug] MIN_DELTA stream emits UPDATE_BEFORE/UPDATE_AFTER when reinserting a deleted MOW key #65808

Description

@yujun777

Description

A direct MIN_DELTA table stream on a MOW UNIQUE KEY table emits UPDATE_BEFORE and UPDATE_AFTER when a key is inserted again after its delete event has already been consumed. From the logical table perspective, the second write should be an APPEND.

This reproduces without IVM and without materialized-view complete refresh.

Reproduction

CREATE TABLE base_table (
    k1 INT,
    v1 INT
) UNIQUE KEY(k1)
DISTRIBUTED BY HASH(k1) BUCKETS 1
PROPERTIES (
    "replication_num" = "1",
    "binlog.enable" = "true",
    "binlog.format" = "ROW",
    "binlog.need_historical_value" = "true",
    "enable_unique_key_merge_on_write" = "true"
);

CREATE STREAM base_stream ON TABLE base_table
PROPERTIES ("type" = "min_delta");

CREATE TABLE tmp_table (k1 INT, v1 INT)
DUPLICATE KEY(k1)
DISTRIBUTED BY HASH(k1) BUCKETS 1
PROPERTIES ("replication_num" = "1");

INSERT INTO base_table VALUES (1, 10);
DELETE FROM base_table WHERE k1 = 1;
INSERT INTO tmp_table SELECT * FROM base_stream;
INSERT INTO base_table VALUES (1, 10);

SET show_hidden_columns = true;
SELECT k1, v1,
       __DORIS_STREAM_CHANGE_TYPE_COL__,
       __DORIS_STREAM_SEQUENCE_COL__
FROM base_stream;

Actual result

k1  v1    __DORIS_STREAM_CHANGE_TYPE_COL__  __DORIS_STREAM_SEQUENCE_COL__
1   NULL  UPDATE_BEFORE                    <sequence>
1   10    UPDATE_AFTER                     <sequence>

The initial insert followed by delete is consumed by the INSERT INTO tmp_table SELECT * FROM base_stream statement, and the stream offset is advanced before the second insert.

Expected result

The second insert should be returned as one logical APPEND row, because the key is absent from the visible table state after the delete was consumed.

Suspected area

MOW keeps a delete tombstone physically. A subsequent write for that key appears to be classified as ROW_BINLOG_UPDATE instead of ROW_BINLOG_APPEND, after which MIN_DELTA expands it to UPDATE_BEFORE plus UPDATE_AFTER. Relevant code paths include historical_row_retriever.cpp and block_reader.cpp.

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions