Skip to content

[fix](binlog) wrap Row Binlog AFTER columns as nullable before conversion - #66553

Open
luwei16 wants to merge 4 commits into
apache:masterfrom
luwei16:fix/doris-27426-row-binlog-null-map
Open

[fix](binlog) wrap Row Binlog AFTER columns as nullable before conversion#66553
luwei16 wants to merge 4 commits into
apache:masterfrom
luwei16:fix/doris-27426-row-binlog-null-map

Conversation

@luwei16

@luwei16 luwei16 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #65951

Related PR: #65810

Problem Summary: Row Binlog makes normal non-key AFTER columns nullable even when their source columns are NOT NULL. OlapBlockDataConvertor derives the null map from the runtime source column, so a non-nullable complex source provides no top-level null map. Nullable ARRAY, MAP, and STRUCT writers can then leave their physical null child empty and abort during segment finalization.

This PR keeps the fix local to Row Binlog:

  • Wrap normal non-key AFTER source columns as ColumnNullable<original> with an all-zero null map before conversion.
  • Keep key columns unchanged, preserve original source columns in full_block, and do not mutate the shared input Block.
  • For partial-update missing AFTER columns, wrap each column filled from the historical Rowset before conversion and append.
  • Restore the original generic ColumnWriter::append() behavior and remove the implicit null-map state, avoiding behavior changes in Scalar, VARIANT, and other common write paths.

The test covers full updates, explicit partial updates, and partial updates whose NOT NULL MAP/STRUCT values are filled from a historical Rowset. It verifies logical readback and the physical top-level null-child row count.

Release note

Fix a BE crash when Row Binlog writes NOT NULL complex columns into nullable AFTER columns.

Check List (For Author)

  • Test: Unit Test
    • ./run-be-ut.sh --run --filter=SegmentFlusherTransformFormatTest.RowBinlogWritesNotNullComplexColumnsToNullableAfterColumns -j 16
    • ./build.sh --be -j96
    • build-support/check-format.sh
    • build-support/run-clang-tidy.sh --base HEAD~2 --build-dir be/ut_build_ASAN
  • Behavior changed: Yes (limited to Row Binlog AFTER conversion)
  • Does this need documentation: No

### What problem does this PR solve?

Issue Number: close apache#65951

Related PR: apache#65810

Problem Summary: Row Binlog AFTER value columns are nullable even when their source columns are NOT NULL. Complex source columns then provide no top-level null map, so nullable ARRAY, MAP, and STRUCT writers wrote payloads without advancing their physical null child. Segment finalization aborted while building the empty child ordinal index. Normalize a missing source null map to an all-non-null map for nullable destinations and verify full and partial Row Binlog writes and readback.

### Release note

Fix a BE crash when Row Binlog writes NOT NULL complex columns into nullable AFTER columns.

### Check List (For Author)

- Test: Unit Test
    - `./run-be-ut.sh --run --filter=SegmentFlusherTransformFormatTest.RowBinlogWritesNotNullComplexColumnsToNullableAfterColumns -j 16`
    - `./build.sh --be -j96`
- Behavior changed: Yes (nullable destinations now persist an all-non-null map when source data has no explicit null map)
- Does this need documentation: No
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@luwei16

luwei16 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29206 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 8f06fedf900b63ab37956c3274d640ab36f33c7f, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17655	4047	4012	4012
q2	2008	326	208	208
q3	10296	1442	816	816
q4	4678	480	343	343
q5	7573	904	571	571
q6	181	174	136	136
q7	742	812	596	596
q8	9311	1558	1647	1558
q9	5368	4127	4090	4090
q10	6789	1620	1351	1351
q11	512	364	332	332
q12	751	609	465	465
q13	18090	3273	2746	2746
q14	263	276	243	243
q15	q16	736	730	653	653
q17	945	891	897	891
q18	6610	5625	5573	5573
q19	1296	1209	1115	1115
q20	813	707	562	562
q21	6239	2842	2633	2633
q22	472	367	312	312
Total cold run time: 101328 ms
Total hot run time: 29206 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5145	4647	4661	4647
q2	288	332	213	213
q3	4925	5287	4651	4651
q4	2220	2267	1438	1438
q5	4734	4388	4388	4388
q6	224	200	146	146
q7	1898	1690	1496	1496
q8	2330	2018	2000	2000
q9	7111	6705	6674	6674
q10	4239	4252	3814	3814
q11	515	371	336	336
q12	702	715	506	506
q13	2968	3293	2767	2767
q14	272	268	242	242
q15	q16	662	679	606	606
q17	1241	1219	1210	1210
q18	12082	10985	11781	10985
q19	1112	1080	1072	1072
q20	2184	2195	1904	1904
q21	5231	4631	4595	4595
q22	504	474	413	413
Total cold run time: 60587 ms
Total hot run time: 54103 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 166383 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 8f06fedf900b63ab37956c3274d640ab36f33c7f, data reload: false

query5	4304	591	464	464
query6	472	223	208	208
query7	4844	621	334	334
query8	325	160	146	146
query9	8777	4019	3997	3997
query10	468	420	309	309
query11	5782	2178	2009	2009
query12	142	103	94	94
query13	1240	558	412	412
query14	6056	4241	3978	3978
query14_1	3759	3759	3754	3754
query15	201	194	177	177
query16	975	450	430	430
query17	899	670	544	544
query18	2507	476	344	344
query19	205	197	148	148
query20	104	101	104	101
query21	231	159	139	139
query22	12997	12945	12742	12742
query23	15884	15110	14560	14560
query23_1	14817	14651	14655	14651
query24	7615	1721	1230	1230
query24_1	1244	1255	1215	1215
query25	578	447	393	393
query26	1325	373	227	227
query27	2587	600	359	359
query28	4605	2035	2014	2014
query29	1086	628	523	523
query30	345	271	228	228
query31	1178	1139	1050	1050
query32	114	68	62	62
query33	538	317	269	269
query34	1198	1137	609	609
query35	749	755	664	664
query36	770	763	711	711
query37	158	107	97	97
query38	1827	1764	1670	1670
query39	838	822	812	812
query39_1	791	797	794	794
query40	247	168	148	148
query41	68	65	63	63
query42	95	94	93	93
query43	311	327	283	283
query44	1415	763	766	763
query45	190	174	165	165
query46	1042	1153	717	717
query47	1522	1511	1467	1467
query48	404	444	292	292
query49	579	401	298	298
query50	1073	436	348	348
query51	10476	10779	10527	10527
query52	88	87	74	74
query53	263	282	193	193
query54	272	243	214	214
query55	76	70	67	67
query56	311	296	294	294
query57	1044	1007	930	930
query58	267	269	252	252
query59	1509	1582	1322	1322
query60	308	267	253	253
query61	171	150	152	150
query62	402	320	269	269
query63	239	197	196	196
query64	2857	1013	828	828
query65	3864	3813	3815	3813
query66	1861	479	361	361
query67	28212	28065	28112	28065
query68	3136	1581	1045	1045
query69	399	306	258	258
query70	880	789	785	785
query71	367	357	311	311
query72	3055	2655	2458	2458
query73	858	764	439	439
query74	4638	4470	4283	4283
query75	2386	2355	1995	1995
query76	2315	1146	774	774
query77	351	386	284	284
query78	11330	11147	10572	10572
query79	1423	1136	771	771
query80	706	579	482	482
query81	466	353	289	289
query82	637	180	140	140
query83	408	334	311	311
query84	328	170	134	134
query85	1030	600	548	548
query86	316	232	224	224
query87	1984	1960	1833	1833
query88	3701	2792	2793	2792
query89	396	324	280	280
query90	2031	197	193	193
query91	206	186	160	160
query92	65	60	62	60
query93	1595	1537	990	990
query94	551	368	320	320
query95	794	588	467	467
query96	1045	774	345	345
query97	2488	2464	2370	2370
query98	196	189	183	183
query99	734	728	609	609
Total cold run time: 252683 ms
Total hot run time: 166383 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.79 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 8f06fedf900b63ab37956c3274d640ab36f33c7f, data reload: false

query1	0.00	0.00	0.00
query2	0.09	0.04	0.04
query3	0.25	0.14	0.13
query4	1.60	0.14	0.14
query5	0.23	0.22	0.22
query6	1.16	0.85	0.83
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.37	0.31	0.30
query10	0.56	0.53	0.55
query11	0.19	0.14	0.14
query12	0.18	0.15	0.14
query13	0.46	0.47	0.47
query14	1.02	0.99	1.00
query15	0.61	0.61	0.58
query16	0.31	0.32	0.32
query17	1.13	1.09	1.07
query18	0.21	0.21	0.20
query19	2.03	1.98	1.93
query20	0.02	0.01	0.02
query21	15.44	0.20	0.13
query22	4.97	0.05	0.06
query23	16.11	0.29	0.12
query24	2.93	0.39	0.32
query25	0.10	0.05	0.05
query26	0.73	0.22	0.14
query27	0.05	0.04	0.04
query28	3.49	0.80	0.33
query29	12.53	4.04	3.16
query30	0.26	0.15	0.15
query31	2.77	0.57	0.31
query32	3.21	0.58	0.48
query33	3.26	3.15	3.14
query34	15.71	3.96	3.28
query35	3.21	3.23	3.23
query36	0.55	0.44	0.42
query37	0.09	0.07	0.06
query38	0.05	0.04	0.03
query39	0.03	0.04	0.04
query40	0.17	0.16	0.14
query41	0.09	0.03	0.02
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.35 s
Total hot run time: 23.79 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100.00% (5/5) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.89% (32281/42536)
Line Coverage 60.75% (361793/595575)
Region Coverage 57.17% (303103/530205)
Branch Coverage 58.62% (137010/233706)

@HappenLee

Copy link
Copy Markdown
Contributor

/review

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: All Codex review accounts are usage-limited; earliest retry is 2026-08-08T03:32:00Z.
Workflow run: https://github.com/apache/doris/actions/runs/31144703622

Please trigger /review again after that time.

### What problem does this PR solve?

Issue Number: close apache#65951

Related PR: apache#65810

Problem Summary: Row Binlog AFTER value columns are nullable even when their source columns are NOT NULL. Complex source columns then provide no top-level null map, so nullable ARRAY, MAP, and STRUCT writers can leave the physical null child empty and abort during segment finalization. Wrap only Row Binlog normal non-key AFTER inputs before OlapBlockDataConvertor, including missing columns filled from historical rows, while preserving the original shared input and full block. Restore the generic ColumnWriter behavior so other write paths are unaffected.

### Release note

Fix a BE crash when Row Binlog writes NOT NULL complex columns into nullable AFTER columns.

### Check List (For Author)

- Test: Unit Test
    - `./run-be-ut.sh --run --filter=SegmentFlusherTransformFormatTest.RowBinlogWritesNotNullComplexColumnsToNullableAfterColumns -j 16`
    - `./build.sh --be -j96`
    - `build-support/check-format.sh`
    - `build-support/run-clang-tidy.sh --base HEAD^ --build-dir be/ut_build_ASAN`
- Behavior changed: Yes (limited to Row Binlog AFTER conversion)
- Does this need documentation: No
@luwei16 luwei16 changed the title [fix](be) Write implicit null maps for nullable columns [fix](be) Scope nullable AFTER conversion to Row Binlog Aug 7, 2026
@luwei16 luwei16 changed the title [fix](be) Scope nullable AFTER conversion to Row Binlog [fix](binlog) wrap Row Binlog AFTER columns as nullable before conversion Aug 7, 2026
_normal_column_ids.end();
}

bool RowBinlogSourceDataWriter::is_after_column(uint32_t source_cid) const {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个名字感觉不是很正确,before也得加nullable,你这也能判断出来before

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确实,这个名字不太准确。这里拿到的是源表列,它本身没有 AFTER 或 BEFORE 的区别,所以我把判断改成 is_row_binlog_value_column,nullable 包装也改成 make_nullable_row_binlog_value_column

prepare_by_source_block() 这条路径里,源表普通 value 列接下来用于写 AFTER,所以局部变量叫 source_column_for_after。BEFORE 不走这里,而是在 _fill_before_columns() 中从历史行单独构造,那里已经处理好了 nullable。

Resolve the Row Binlog test conflict after independent source and binlog tablets were introduced. Keep nullable AFTER conversion coverage on the new tablet-pair architecture.

namespace {

ColumnWithTypeAndName make_nullable_after_column(const ColumnWithTypeAndName& source) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

还有这个命名

Rename the source-column predicate and nullable wrapper so they describe Row Binlog value columns instead of implying the source cid identifies an AFTER column.
@luwei16

luwei16 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28687 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 2b1ccb37e259f566f127f34e856868eb8e0638e6, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17694	4018	3984	3984
q2	2033	320	197	197
q3	10289	1390	836	836
q4	4681	465	337	337
q5	7548	831	545	545
q6	184	180	138	138
q7	761	808	587	587
q8	9675	1344	1437	1344
q9	5880	4079	4042	4042
q10	6816	1645	1380	1380
q11	512	362	331	331
q12	725	565	460	460
q13	18132	3189	2714	2714
q14	258	262	237	237
q15	q16	724	727	659	659
q17	1024	992	984	984
q18	6475	5567	5562	5562
q19	1287	1247	1008	1008
q20	817	659	549	549
q21	5827	2612	2487	2487
q22	446	362	306	306
Total cold run time: 101788 ms
Total hot run time: 28687 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4354	4258	4342	4258
q2	281	316	212	212
q3	4537	4889	4362	4362
q4	2159	2258	1425	1425
q5	4223	4070	4139	4070
q6	227	175	129	129
q7	1708	1596	1418	1418
q8	2771	2222	2152	2152
q9	7226	7212	7219	7212
q10	4263	4273	3890	3890
q11	577	422	364	364
q12	765	727	514	514
q13	3197	3597	2867	2867
q14	290	327	273	273
q15	q16	687	733	655	655
q17	1363	1317	1313	1313
q18	12120	11078	11732	11078
q19	1198	1147	1154	1147
q20	2234	2239	1936	1936
q21	5680	4842	4497	4497
q22	507	475	409	409
Total cold run time: 60367 ms
Total hot run time: 54181 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 157467 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 2b1ccb37e259f566f127f34e856868eb8e0638e6, data reload: false

query5	4307	587	440	440
query6	463	217	204	204
query7	4844	613	325	325
query8	312	159	157	157
query9	8749	4010	4019	4010
query10	449	345	314	314
query11	5704	2226	2003	2003
query12	155	100	96	96
query13	1267	580	450	450
query14	6081	4285	4026	4026
query14_1	3807	3773	3794	3773
query15	200	196	179	179
query16	980	477	441	441
query17	934	702	562	562
query18	2439	471	343	343
query19	209	185	157	157
query20	108	100	102	100
query21	231	158	130	130
query22	13176	13071	12807	12807
query23	15659	15071	14559	14559
query23_1	14567	14627	14519	14519
query24	7591	1692	1240	1240
query24_1	1243	1242	1249	1242
query25	553	436	383	383
query26	1306	396	230	230
query27	2573	570	387	387
query28	4575	2036	2012	2012
query29	1107	625	498	498
query30	336	269	218	218
query31	1158	1107	1047	1047
query32	98	61	62	61
query33	538	312	261	261
query34	1207	1165	641	641
query35	742	752	662	662
query36	750	775	699	699
query37	157	111	92	92
query38	1829	1777	1674	1674
query39	823	820	796	796
query39_1	788	796	813	796
query40	332	164	152	152
query41	71	71	68	68
query42	99	98	95	95
query43	314	316	278	278
query44	1417	766	766	766
query45	190	178	170	170
query46	1123	1202	707	707
query47	1554	1571	1456	1456
query48	430	425	303	303
query49	587	450	289	289
query50	1066	433	325	325
query51	10667	10539	10316	10316
query52	85	87	74	74
query53	262	265	199	199
query54	282	227	225	225
query55	74	70	67	67
query56	281	274	306	274
query57	1014	1012	927	927
query58	285	248	236	236
query59	1508	1599	1390	1390
query60	316	269	253	253
query61	147	148	144	144
query62	389	314	267	267
query63	234	197	193	193
query64	2805	1034	833	833
query65	3857	3793	3737	3737
query66	1842	464	366	366
query67	19861	20067	19857	19857
query68	3308	1530	1045	1045
query69	390	289	276	276
query70	869	774	758	758
query71	368	337	309	309
query72	3012	2576	2321	2321
query73	827	767	441	441
query74	4588	4526	4273	4273
query75	2352	2319	2014	2014
query76	2315	1139	763	763
query77	341	367	271	271
query78	11095	11054	10564	10564
query79	1376	1155	763	763
query80	1264	551	465	465
query81	515	332	278	278
query82	669	178	133	133
query83	371	322	301	301
query84	336	161	130	130
query85	966	604	508	508
query86	401	240	217	217
query87	1987	1947	1832	1832
query88	3700	2807	2756	2756
query89	409	311	281	281
query90	1911	193	188	188
query91	203	186	159	159
query92	62	56	56	56
query93	1721	1531	1010	1010
query94	717	344	298	298
query95	784	505	478	478
query96	1114	798	343	343
query97	2455	2434	2310	2310
query98	200	182	182	182
query99	733	735	616	616
Total cold run time: 244752 ms
Total hot run time: 157467 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.58 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 2b1ccb37e259f566f127f34e856868eb8e0638e6, data reload: false

query1	0.00	0.00	0.01
query2	0.10	0.05	0.04
query3	0.26	0.13	0.13
query4	1.62	0.14	0.14
query5	0.24	0.21	0.23
query6	1.16	0.82	0.79
query7	0.04	0.01	0.00
query8	0.05	0.04	0.04
query9	0.37	0.31	0.30
query10	0.56	0.55	0.58
query11	0.19	0.13	0.13
query12	0.17	0.15	0.14
query13	0.47	0.45	0.45
query14	0.99	0.98	0.98
query15	0.59	0.57	0.60
query16	0.31	0.31	0.32
query17	1.09	1.07	1.09
query18	0.21	0.21	0.20
query19	2.08	1.83	1.86
query20	0.02	0.02	0.02
query21	15.44	0.18	0.13
query22	5.03	0.05	0.05
query23	16.11	0.32	0.12
query24	2.89	0.42	0.33
query25	0.11	0.06	0.04
query26	0.71	0.21	0.16
query27	0.04	0.04	0.03
query28	3.53	0.74	0.35
query29	12.51	4.02	3.18
query30	0.26	0.15	0.15
query31	2.77	0.56	0.31
query32	3.23	0.59	0.47
query33	3.14	3.09	3.24
query34	15.71	3.92	3.28
query35	3.22	3.22	3.19
query36	0.55	0.43	0.44
query37	0.08	0.06	0.07
query38	0.05	0.04	0.03
query39	0.03	0.04	0.03
query40	0.17	0.15	0.15
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.04
Total cold run time: 96.26 s
Total hot run time: 23.58 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100.00% (21/21) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.94% (32315/42555)
Line Coverage 60.78% (362223/595949)
Region Coverage 57.46% (304703/530316)
Branch Coverage 58.89% (137763/233948)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug](Highest) BE can crash in OrdinalIndexWriter::finish during binlog workload flush

3 participants