jfeng9282 opened a new issue, #70427:
URL: https://github.com/apache/doris/issues/70427

   ### Search before asking
   
   - [x] I had searched in the 
[issues](https://github.com/apache/doris/issues?q=is%3Aissue) and found no 
similar issues.
   
   
   ### Version
   
   doris 4.1.3
   
   ### What's Wrong?
   
   English:
   After an UPDATE on a Unique Key MoW table with store_row_column = true, a 
primary-key point query (SELECT * ... WHERE id = 'xxx' without LIMIT) may 
return historical, stale versions of the row instead of the latest committed 
data.
   
   This is a severe data correctness issue. Key observations:
   
   · Long-term persistence: The stale data can still be queried long after the 
update (e.g., consecutive 100 queries return the same historical version).
   · Multiple historical versions: Different old versions can be returned 
across queries.
   · High reproducibility: Occurs with a frequency >50% under specific 
conditions.
   · Cache exclusion: Excluding enable_sql_cache (tested both on and off).
   · LIMIT difference: The bug seems not reproducible when a LIMIT clause is 
added to the query. GUI clients like DBeaver automatically append LIMIT, which 
may hide the issue.
   
   中文补充:
   在开启了行存(store_row_column = true)的 Unique Key MoW 表上,执行 UPDATE 后,通过主键进行点查(不带 
LIMIT),高概率(>50%)查询到历史旧版本数据,且能查到多个旧版本。等待很久依然如此(曾连续100次查询同一旧版本),已排除 SQL 
缓存的影响。关键发现:带上 LIMIT 后暂时未发现复现情况(需注意 DBeaver 等可视化工具会自动追加 LIMIT,导致难以复现)。
   
   ### What You Expected?
   
   English:
   After a successful UPDATE, all subsequent SELECT queries (regardless of 
using LIMIT or not) should return only the latest committed version of the row. 
Historical versions should never be visible.
   
   中文补充:
   更新成功后,后续查询(无论是否带 LIMIT)应当且仅当返回最新提交的数据,不应再查询到任何历史旧版本。
   
   ### How to Reproduce?
   
   DDL:
   CREATE TABLE `base_series` (
     `id` varchar(50) NOT NULL COMMENT "主键id",
     `type` varchar(50) NOT NULL COMMENT "类型",
     -- ... (其他字段省略) ...
     INDEX idx_name (`name`) USING INVERTED,
     INDEX idx_type (`type`) USING INVERTED
   ) ENGINE=OLAP
   UNIQUE KEY(`id`)
   DISTRIBUTED BY HASH(`id`) BUCKETS 1
   PROPERTIES (
   "replication_allocation" = "tag.location.default: 3",
   "enable_unique_key_merge_on_write" = "true",
   "store_row_column" = "true",
   "row_store_page_size" = "4096"
   -- ... (其他属性省略) ...
   );
   
   Steps (复现步骤):
   Note: Please test via MySQL CLI or your application code directly. Avoid GUI 
clients (like DBeaver/Navicat) as they may automatically append LIMIT and 
prevent reproduction.
   (注意:请使用 MySQL 命令行或代码直接执行,不要用 DBeaver 等图形化界面,因为它们会自动加 LIMIT 导致无法复现。)
   
   1. Insert data: INSERT INTO base_series (id, type, ...) VALUES ('test_id', 
'A', ...);
   2. Update data: UPDATE base_series SET type = 'B' WHERE id = 'test_id';
   3. Query data without LIMIT: SELECT * FROM base_series WHERE id = 'test_id';
   4. Observed (观察到的现象): The query returns the old version (type='A') instead 
of type='B'.
   
   ### Anything Else?
   
   Preliminary Root Cause Localization (初步定位):
   I found that the execution plan contains a SHORT-CIRCUIT operator when 
executing the query without LIMIT. When I disabled short-circuit query by 
setting SET enable_short_circuit_query = false;, the query immediately returned 
the correct latest data. This strongly indicates the issue lies within the 
short-circuit query path for MoW with row store, possibly related to the query 
plan differences when LIMIT is present.
   (我发现在不带 LIMIT 执行查询时,执行计划中包含 SHORT-CIRCUIT(短路查询)算子。当我通过设置 SET 
enable_short_circuit_query = false; 禁用短路查询后,查询立刻返回了正确的最新数据。这强烈表明问题出在开启行存的 MoW 
表的短路查询路径中,可能与带 LIMIT 时的查询计划差异有关。)
   
   Related existing records (相关历史记录):
   I found Issue #34056 and PR #65051, both pointing to correctness/crash risks 
in the short-circuit row-store MoW path. However, the reported behavior there 
is different from mine: #34056 returns wrong default values, while my case 
returns stale historical versions of a row after UPDATE. This suggests the 
short-circuit path may have a separate version-visibility defect not covered by 
existing fixes.
   (我发现了 Issue #34056 和 PR 
#65051,它们都指向短路查询+行存+MoW路径的正确性/崩溃风险。但是,那里报告的行为与我的不同:#34056 返回了错误的默认值,而我的情况是 
UPDATE 之后返回了历史旧版本数据。这表明短路路径可能存在一个未被现有修复覆盖的、独立的版本可见性缺陷。)
   
   Workaround (规避方案):
   Set enable_short_circuit_query = false to temporarily avoid this issue, or 
add a LIMIT clause to the query. However, this disables the point-query 
optimization or changes the query semantics.
   (设置 enable_short_circuit_query = false 可以临时规避此问题,或者在查询中加上 LIMIT 
子句。但是,这会禁用点查优化或改变查询语义。)
   
   Context (背景说明):
   I am a user encountering this in a real-world scenario. I have identified 
the triggering conditions and a workaround, but I do not have the capacity to 
locate the underlying code root cause. I am submitting this public issue to 
formally track this severe data-correctness bug and hope the community can fix 
it.
   (中文翻译:我是在真实业务场景中遇到此问题的用户。我已经定位了触发条件和规避方案,但我没有能力去排查底层的代码根因。我提交这个公开 
Issue,是为了正式追踪这个严重的数据正确性问题,并希望社区能修复它。)
   
   ### Are you willing to submit PR?
   
   - [ ] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://www.apache.org/foundation/policies/conduct)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to