Skip to content

[opt](txn) Per-transaction locking and parallel publish for DatabaseTransactionMgr#59990

Open
dataroaring wants to merge 3 commits intoapache:masterfrom
dataroaring:database_transaction_lock
Open

[opt](txn) Per-transaction locking and parallel publish for DatabaseTransactionMgr#59990
dataroaring wants to merge 3 commits intoapache:masterfrom
dataroaring:database_transaction_lock

Conversation

@dataroaring
Copy link
Contributor

@dataroaring dataroaring commented Jan 17, 2026

Summary

  • Replace database-wide write lock with per-transaction synchronized(transactionState) for commit, preCommit, abort, and finish paths, so independent transactions proceed concurrently
  • Enable parallel publish within a single database by routing publish executors by transactionId instead of dbId
  • Move edit log writes outside the write lock to reduce lock hold time
  • Add config flags for runtime control and safe fallback

Fixes: #53642

Changes

Per-transaction locking (DatabaseTransactionMgr.java)

  • Extract updateTxnLabels from unprotectUpdateInMemoryState — only needed at beginTransaction and replay time, not during state transitions
  • Convert runningTxnNums from volatile int to AtomicInteger for thread-safe increment/decrement without db lock
  • Replace ArrayDeque with ConcurrentLinkedDeque for final-status transaction queues
  • Replace writeLock()/writeUnlock() with synchronized(transactionState) in:
    • preCommitTransaction2PC
    • commitTransaction (both overloads)
    • finishTransaction
    • abortTransaction / abortTransaction2PC
  • DB write lock retained for: beginTransaction (label uniqueness), removeUselessTxns/cleanLabel (touch labelToTxnIds HashMap), replay paths

Parallel publish within a database (PublishVersionDaemon.java)

  • Route publish executor by transactionId instead of dbId when enable_per_txn_publish=true, so different transactions in the same DB finish in parallel
  • Fix race condition: use local variables in tryFinishTxnSync instead of shared instance fields for partitionVisibleVersions/backendPartitions
  • Rename dbExecutors to publishExecutors

Edit log outside lock (DatabaseTransactionMgr.java, EditLog.java)

  • Enqueue edit log inside lock (nanoseconds), await outside lock (milliseconds)
  • Add enable_txn_log_outside_lock config flag

Config flags (Config.java)

  • enable_per_txn_publish (default true, mutable=true): controls publish routing. Set to false to fall back to sequential-per-DB publish
  • enable_txn_log_outside_lock (default true, mutable=true): controls edit log write location

Correctness

Two different transactions committing concurrently (the main win):

  • Thread A: synchronized(txn1) { set COMMITTED, ConcurrentMap.put }
  • Thread B: synchronized(txn2) { set COMMITTED, ConcurrentMap.put }
  • Different locks, different map entries → fully concurrent

Same transaction: concurrent commit + abort:

  • synchronized(txnState) serializes them — second thread sees the first's state change and handles accordingly

No deadlock: State transition paths only acquire per-txn locks. Cleanup/replay paths only acquire db write lock. No path acquires both.

Test plan

  • Run DatabaseTransactionMgrTest unit tests
  • Concurrent load testing with multiple tables in same database
  • Verify lock hold time reduction via metrics
  • Toggle enable_per_txn_publish at runtime — verify both parallel and sequential modes work
  • Toggle enable_txn_log_outside_lock at runtime — verify both paths work

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings January 17, 2026 06:13
@hello-stephen
Copy link
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?

@dataroaring
Copy link
Contributor Author

run buildall

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request introduces two major changes: (1) reduces lock contention in DatabaseTransactionMgr by moving edit log operations outside write locks, and (2) adds support for flexible partial update mode in routine load operations.

Changes:

  • Refactored DatabaseTransactionMgr to split in-memory state updates from edit log persistence for reduced lock contention
  • Added comprehensive support for unique_key_update_mode property with new UPDATE_FLEXIBLE_COLUMNS mode
  • Introduced validation framework for flexible partial update constraints in OlapTable

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
fe/fe-core/src/main/java/org/apache/doris/transaction/DatabaseTransactionMgr.java Core refactoring: splits unprotectUpsertTransactionState into unprotectUpdateInMemoryState (inside lock) and persistTransactionState (outside lock); applies pattern to transaction lifecycle methods
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateRoutineLoadInfo.java Adds parsing, validation, and property management for unique_key_update_mode with backward compatibility for partial_columns
fe/fe-core/src/main/java/org/apache/doris/load/routineload/RoutineLoadJob.java Updates job properties handling to support new update mode; adds validation logic for ALTER operations
fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java Adds validateForFlexiblePartialUpdate() method to centralize table-level constraint validation
fe/fe-core/src/main/java/org/apache/doris/nereids/load/NereidsStreamLoadPlanner.java Refactors flexible partial update validation to use centralized OlapTable method
fe/fe-core/src/main/java/org/apache/doris/nereids/load/NereidsRoutineLoadTaskInfo.java Updates constructor to accept TUniqueKeyUpdateMode instead of boolean isPartialUpdate flag
fe/fe-core/src/main/java/org/apache/doris/load/routineload/KafkaRoutineLoadJob.java Updates method signature and calls to support UserException for ALTER operations
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterRoutineLoadCommand.java Adds validation for unique_key_update_mode property during ALTER ROUTINE LOAD
regression-test/suites/load_p0/routine_load/test_routine_load_flexible_partial_update.groovy Comprehensive 1414-line test suite with 21 test cases covering flexible partial update feature
regression-test/data/load_p0/routine_load/test_routine_load_flexible_partial_update.out Expected test outputs for flexible partial update test cases
fe/fe-core/src/test/java/org/apache/doris/load/routineload/RoutineLoadJobTest.java Unit tests for unique_key_update_mode parsing, validation, and backward compatibility

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

writeUnlock();
}
// Persist edit log outside lock to reduce lock contention
persistTransactionState(transactionState);
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

The persistTransactionState method is called outside the write lock with a transactionState variable that could potentially be null if an exception is thrown inside the try block before line 372. If any of the checks before line 372 throw an exception (such as checkRunningTxnExceedLimit at line 369), transactionState will remain null and calling persistTransactionState(transactionState) at line 384 would result in a NullPointerException. Consider adding a null check before calling persistTransactionState, or wrapping the call in a condition that ensures transactionState is not null.

Suggested change
persistTransactionState(transactionState);
if (transactionState != null) {
persistTransactionState(transactionState);
}

Copilot uses AI. Check for mistakes.
(
"max_batch_interval" = "10",
"format" = "json",
"jsonpaths" = '["\\$.id", "\\$.name", "\\$.score"]',
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Inconsistent string escaping for jsonpaths property. Line 276 uses single quotes with backslash escaping '["\$.id", ...]', while line 982 uses double quotes with triple backslash escaping "[\"\$.id\", ...]". Both tests should use the same escaping pattern for consistency and readability. Consider standardizing on one approach throughout the test file.

Suggested change
"jsonpaths" = '["\\$.id", "\\$.name", "\\$.score"]',
"jsonpaths" = "[\\\"\\$.id\\", \\\"\\$.name\\", \\\"\\$.score\\"]",

Copilot uses AI. Check for mistakes.
@doris-robot
Copy link

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

------ Round 1 ----------------------------------
q1	17655	4262	4123	4123
q2	2013	351	242	242
q3	10169	1237	693	693
q4	10205	838	300	300
q5	7517	2071	1790	1790
q6	188	171	136	136
q7	918	771	651	651
q8	9271	1381	1123	1123
q9	4759	4653	4542	4542
q10	6757	1815	1411	1411
q11	511	290	278	278
q12	676	737	578	578
q13	17769	3812	3097	3097
q14	284	286	288	286
q15	581	508	508	508
q16	680	696	612	612
q17	653	735	557	557
q18	6535	6463	6536	6463
q19	1109	975	611	611
q20	395	356	258	258
q21	2954	2447	2247	2247
q22	1064	988	945	945
Total cold run time: 102663 ms
Total hot run time: 31451 ms

----- Round 2, with runtime_filter_mode=off -----
q1	4082	4051	4028	4028
q2	345	403	313	313
q3	2091	2584	2179	2179
q4	1289	1776	1289	1289
q5	4119	4055	4070	4055
q6	216	170	128	128
q7	1884	1803	1671	1671
q8	2773	2448	2433	2433
q9	7301	7288	7172	7172
q10	2416	2700	2356	2356
q11	524	484	455	455
q12	710	775	641	641
q13	3705	3998	3367	3367
q14	422	331	282	282
q15	627	604	565	565
q16	641	668	615	615
q17	1119	1302	1404	1302
q18	8101	8075	7785	7785
q19	876	860	822	822
q20	1990	2103	1885	1885
q21	4712	4475	4234	4234
q22	1039	1018	969	969
Total cold run time: 50982 ms
Total hot run time: 48546 ms

@doris-robot
Copy link

TPC-DS: Total hot run time: 174418 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 96357c83754b3cbdeae0f7c23b6a7a7d23995652, data reload: false

query5	4433	613	486	486
query6	329	230	205	205
query7	4216	465	258	258
query8	339	265	244	244
query9	8726	2905	2877	2877
query10	544	361	334	334
query11	15309	15330	14967	14967
query12	180	113	114	113
query13	1253	501	380	380
query14	5786	3024	2822	2822
query14_1	2601	2616	2633	2616
query15	196	192	176	176
query16	978	469	457	457
query17	1067	648	519	519
query18	2412	424	320	320
query19	210	215	183	183
query20	116	111	110	110
query21	209	135	116	116
query22	3787	3927	3818	3818
query23	15939	15680	15361	15361
query23_1	15513	15592	15448	15448
query24	7175	1521	1153	1153
query24_1	1149	1189	1159	1159
query25	507	429	382	382
query26	1235	257	150	150
query27	2776	435	272	272
query28	4609	2163	2152	2152
query29	736	541	411	411
query30	308	240	207	207
query31	799	623	551	551
query32	90	79	74	74
query33	511	355	309	309
query34	904	878	540	540
query35	715	744	692	692
query36	872	917	847	847
query37	130	95	84	84
query38	2657	2705	2587	2587
query39	786	753	742	742
query39_1	740	713	709	709
query40	216	159	118	118
query41	67	68	65	65
query42	103	101	107	101
query43	427	439	420	420
query44	1303	742	742	742
query45	187	185	172	172
query46	832	943	573	573
query47	1424	1510	1436	1436
query48	315	320	240	240
query49	597	446	361	361
query50	607	269	211	211
query51	3765	3764	3879	3764
query52	103	104	92	92
query53	295	321	267	267
query54	277	263	257	257
query55	80	81	77	77
query56	304	305	335	305
query57	979	1017	929	929
query58	276	266	260	260
query59	2066	2175	2032	2032
query60	349	331	327	327
query61	153	147	148	147
query62	375	346	306	306
query63	295	271	268	268
query64	4969	1345	1065	1065
query65	3766	3714	3726	3714
query66	1472	449	329	329
query67	15610	15574	15540	15540
query68	2487	1100	779	779
query69	451	374	332	332
query70	973	955	939	939
query71	318	316	298	298
query72	5485	3363	3409	3363
query73	615	736	320	320
query74	8830	8708	8560	8560
query75	2715	2814	2471	2471
query76	2276	1051	685	685
query77	361	393	310	310
query78	9748	9795	9169	9169
query79	1472	903	571	571
query80	1308	563	491	491
query81	537	268	237	237
query82	986	148	110	110
query83	332	253	236	236
query84	249	109	98	98
query85	898	511	420	420
query86	410	304	295	295
query87	2826	2840	2757	2757
query88	3463	2566	2560	2560
query89	374	341	335	335
query90	2012	174	163	163
query91	188	157	138	138
query92	73	82	68	68
query93	1073	895	544	544
query94	644	322	285	285
query95	577	388	322	322
query96	634	503	231	231
query97	2353	2383	2346	2346
query98	213	200	197	197
query99	594	598	517	517
Total cold run time: 246600 ms
Total hot run time: 174418 ms

@doris-robot
Copy link

ClickBench: Total hot run time: 27.05 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 96357c83754b3cbdeae0f7c23b6a7a7d23995652, data reload: false

query1	0.06	0.05	0.05
query2	0.08	0.05	0.04
query3	0.26	0.08	0.09
query4	1.60	0.11	0.11
query5	0.27	0.26	0.25
query6	1.14	0.66	0.66
query7	0.03	0.02	0.02
query8	0.05	0.03	0.04
query9	0.57	0.50	0.49
query10	0.56	0.54	0.56
query11	0.14	0.09	0.10
query12	0.15	0.10	0.11
query13	0.59	0.58	0.59
query14	0.94	0.94	0.96
query15	0.78	0.78	0.79
query16	0.41	0.41	0.43
query17	1.03	1.00	0.98
query18	0.23	0.22	0.21
query19	1.88	1.75	1.76
query20	0.02	0.01	0.01
query21	15.46	0.28	0.14
query22	4.86	0.06	0.04
query23	15.68	0.28	0.10
query24	1.84	0.69	0.58
query25	0.08	0.10	0.07
query26	0.14	0.12	0.14
query27	0.05	0.05	0.10
query28	5.33	1.06	0.89
query29	12.56	3.89	3.17
query30	0.28	0.14	0.13
query31	2.81	0.61	0.40
query32	3.23	0.55	0.45
query33	3.02	3.05	3.11
query34	16.20	5.11	4.45
query35	4.44	4.44	4.43
query36	0.63	0.51	0.50
query37	0.10	0.06	0.07
query38	0.07	0.04	0.04
query39	0.04	0.03	0.04
query40	0.17	0.14	0.13
query41	0.08	0.03	0.04
query42	0.04	0.03	0.03
query43	0.04	0.04	0.04
Total cold run time: 97.94 s
Total hot run time: 27.05 s

@hello-stephen
Copy link
Contributor

FE UT Coverage Report

Increment line coverage 27.61% (45/163) 🎉
Increment coverage report
Complete coverage report

Move edit log operations outside the write lock to improve transaction
throughput for concurrent operations on different tables within the
same database.

Changes:
- Add unprotectUpdateInMemoryState() for in-memory updates inside lock
- Add persistTransactionState() for edit log writes outside lock
- Refactor beginTransaction, commitTransaction, finishTransaction,
  abortTransaction, and removeUselessTxns to use the new pattern
- Refactor unprotectUpsertTransactionState to delegate to new methods

This reduces lock hold time from milliseconds (I/O bound) to microseconds
(memory only), enabling higher concurrency for multi-table workloads.

Safety is maintained because:
- In-memory state is updated atomically within the write lock
- Edit log failures call System.exit(-1), preventing inconsistent state
- Replay path remains unchanged (uses isReplay=true)

Fixes: apache#53642
@dataroaring dataroaring force-pushed the database_transaction_lock branch from 96357c8 to a105828 Compare February 7, 2026 06:58
@dataroaring
Copy link
Contributor Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

Reviewed the lock contention optimization in DatabaseTransactionMgr. The pattern of splitting unprotectUpsertTransactionState into unprotectUpdateInMemoryState (inside lock) and persistTransactionState (outside lock) is sound. Exception paths in beginTransaction, preCommitTransaction2PC, commitTransaction, and abortTransaction are safe because Java try-finally semantics ensure persistTransactionState is only reached when the try block completes normally.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@dataroaring dataroaring force-pushed the database_transaction_lock branch from 2d07df9 to 10ed461 Compare February 7, 2026 07:41
@dataroaring dataroaring changed the title [Enhancement] Reduce lock contention in DatabaseTransactionMgr [opt](txn) Reduce lock contention in DatabaseTransactionMgr Feb 7, 2026
@dataroaring
Copy link
Contributor Author

run buildall

@doris-robot
Copy link

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

------ Round 1 ----------------------------------
q1	16423	4485	4287	4287
q2	2005	362	226	226
q3	9739	1253	707	707
q4	9867	759	306	306
q5	7460	2158	1891	1891
q6	194	173	151	151
q7	862	740	602	602
q8	9167	1351	1055	1055
q9	4556	4620	4522	4522
q10	6808	1931	1544	1544
q11	532	322	297	297
q12	337	379	225	225
q13	17459	4071	3219	3219
q14	230	229	223	223
q15	868	804	802	802
q16	684	661	606	606
q17	672	813	547	547
q18	6414	5748	5558	5558
q19	1090	980	634	634
q20	498	482	385	385
q21	2509	1772	1777	1772
q22	361	314	284	284
Total cold run time: 98735 ms
Total hot run time: 29843 ms

----- Round 2, with runtime_filter_mode=off -----
q1	4333	4328	4342	4328
q2	255	348	255	255
q3	2055	2668	2174	2174
q4	1334	1733	1284	1284
q5	4278	4248	4243	4243
q6	210	176	135	135
q7	1833	1824	1692	1692
q8	2455	2275	2291	2275
q9	8045	7578	7549	7549
q10	2942	3047	2582	2582
q11	563	474	468	468
q12	701	752	603	603
q13	3822	4384	3563	3563
q14	300	373	311	311
q15	867	792	808	792
q16	764	754	680	680
q17	1171	1349	1459	1349
q18	8333	7820	7999	7820
q19	953	854	892	854
q20	2057	2141	2004	2004
q21	4804	4570	4061	4061
q22	619	556	507	507
Total cold run time: 52694 ms
Total hot run time: 49529 ms

@doris-robot
Copy link

ClickBench: Total hot run time: 28.06 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 10ed4611fe7ac041712bd3c61e9996f5b019db2f, data reload: false

query1	0.06	0.05	0.04
query2	0.14	0.07	0.07
query3	0.31	0.08	0.07
query4	1.60	0.10	0.09
query5	0.26	0.25	0.25
query6	1.14	0.65	0.65
query7	0.04	0.03	0.03
query8	0.07	0.06	0.06
query9	0.58	0.51	0.50
query10	0.55	0.56	0.55
query11	0.27	0.13	0.14
query12	0.27	0.14	0.14
query13	0.62	0.61	0.60
query14	0.98	0.98	0.98
query15	0.91	0.82	0.82
query16	0.40	0.36	0.40
query17	1.00	1.02	1.08
query18	0.24	0.23	0.22
query19	1.96	1.83	1.82
query20	0.02	0.01	0.01
query21	15.41	0.33	0.28
query22	4.94	0.13	0.13
query23	15.33	0.44	0.27
query24	2.40	0.54	0.37
query25	0.11	0.10	0.11
query26	0.19	0.18	0.18
query27	0.10	0.10	0.10
query28	3.62	1.15	0.98
query29	12.50	4.09	3.29
query30	0.32	0.13	0.13
query31	2.80	0.68	0.43
query32	3.23	0.62	0.51
query33	3.04	3.00	3.06
query34	15.85	5.12	4.45
query35	4.50	4.42	4.47
query36	0.60	0.51	0.49
query37	0.29	0.08	0.08
query38	0.27	0.06	0.06
query39	0.08	0.05	0.05
query40	0.21	0.17	0.17
query41	0.13	0.06	0.06
query42	0.10	0.05	0.04
query43	0.06	0.06	0.06
Total cold run time: 97.5 s
Total hot run time: 28.06 s

@hello-stephen
Copy link
Contributor

FE Regression Coverage Report

Increment line coverage 58.62% (68/116) 🎉
Increment coverage report
Complete coverage report

@dataroaring dataroaring force-pushed the database_transaction_lock branch 2 times, most recently from d4fe88e to 24e0b10 Compare February 7, 2026 16:16
@dataroaring
Copy link
Contributor Author

run buildall

@dataroaring dataroaring force-pushed the database_transaction_lock branch 3 times, most recently from cda43c3 to d4a38b8 Compare February 7, 2026 17:10
@dataroaring
Copy link
Contributor Author

run buildall

@doris-robot
Copy link

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

------ Round 1 ----------------------------------
q1	17440	4455	4285	4285
q2	2041	338	238	238
q3	10189	1261	726	726
q4	10199	780	305	305
q5	7516	2175	1980	1980
q6	206	181	146	146
q7	901	729	607	607
q8	9272	1347	1227	1227
q9	4716	4618	4547	4547
q10	6760	1946	1554	1554
q11	506	304	277	277
q12	345	388	226	226
q13	17765	4003	3300	3300
q14	228	231	213	213
q15	865	796	818	796
q16	689	689	622	622
q17	696	816	529	529
q18	6523	5788	6059	5788
q19	1175	1107	655	655
q20	545	530	427	427
q21	2869	1940	1928	1928
q22	414	333	307	307
Total cold run time: 101860 ms
Total hot run time: 30683 ms

----- Round 2, with runtime_filter_mode=off -----
q1	4614	4493	4543	4493
q2	283	347	280	280
q3	2428	2907	2365	2365
q4	1436	1841	1440	1440
q5	4809	4814	4618	4618
q6	211	178	139	139
q7	1961	1885	1745	1745
q8	2590	2336	2354	2336
q9	7327	7829	7379	7379
q10	2853	2960	2615	2615
q11	562	480	440	440
q12	686	687	563	563
q13	3567	4013	3236	3236
q14	268	284	262	262
q15	817	788	773	773
q16	631	691	638	638
q17	1055	1219	1311	1219
q18	7425	7473	7174	7174
q19	852	798	798	798
q20	1943	2057	1885	1885
q21	4531	4300	4076	4076
q22	562	542	510	510
Total cold run time: 51411 ms
Total hot run time: 48984 ms

@dataroaring dataroaring force-pushed the database_transaction_lock branch from d4a38b8 to 44fbda7 Compare February 7, 2026 17:43
@dataroaring
Copy link
Contributor Author

run buildall

@dataroaring dataroaring force-pushed the database_transaction_lock branch from 44fbda7 to 859f56d Compare February 7, 2026 18:10
@doris-robot
Copy link

ClickBench: Total hot run time: 28.08 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 44fbda7b4e3aa6922f944bb0855448166d8f85ce, data reload: false

query1	0.05	0.05	0.05
query2	0.14	0.07	0.07
query3	0.31	0.08	0.08
query4	1.60	0.10	0.09
query5	0.25	0.25	0.24
query6	1.14	0.64	0.64
query7	0.03	0.02	0.02
query8	0.08	0.06	0.07
query9	0.59	0.49	0.49
query10	0.55	0.57	0.55
query11	0.26	0.13	0.13
query12	0.26	0.14	0.14
query13	0.62	0.62	0.59
query14	0.98	0.98	0.98
query15	0.91	0.83	0.82
query16	0.40	0.38	0.38
query17	1.06	1.01	1.05
query18	0.25	0.23	0.23
query19	1.96	1.81	1.72
query20	0.02	0.02	0.01
query21	15.39	0.34	0.29
query22	4.95	0.12	0.14
query23	15.31	0.46	0.29
query24	2.33	0.60	0.39
query25	0.12	0.11	0.11
query26	0.20	0.19	0.18
query27	0.12	0.10	0.10
query28	3.64	1.17	0.99
query29	12.54	4.15	3.31
query30	0.32	0.13	0.11
query31	2.80	0.67	0.45
query32	3.23	0.64	0.51
query33	2.97	3.07	3.03
query34	16.22	5.00	4.46
query35	4.53	4.43	4.48
query36	0.60	0.49	0.49
query37	0.32	0.09	0.09
query38	0.28	0.07	0.06
query39	0.08	0.04	0.05
query40	0.21	0.16	0.16
query41	0.14	0.07	0.07
query42	0.09	0.05	0.05
query43	0.06	0.06	0.05
Total cold run time: 97.91 s
Total hot run time: 28.08 s

@hello-stephen
Copy link
Contributor

FE UT Coverage Report

Increment line coverage 21.14% (26/123) 🎉
Increment coverage report
Complete coverage report

…ock optimization

Add enable_txn_log_outside_lock config (default true) to control whether
transaction edit log writes happen inside or outside the write lock.

When enabled, edit log entries are enqueued (FIFO) inside the write lock and
awaited outside it, preserving ordering via the batch queue while reducing
lock hold time. This resolves the potential out-of-order edit log issue from
the previous outside-lock optimization.

- Add submitEdit() split API to EditLog for enqueue-only writes
- Make EditLogItem public with await() method
- Add enqueueTransactionState/awaitTransactionState helpers
- Update all 8 persist call sites in DatabaseTransactionMgr
@dataroaring dataroaring force-pushed the database_transaction_lock branch from 859f56d to 1bc3156 Compare February 7, 2026 19:10
…n a database

Replace the database-wide write lock with synchronized(transactionState) for
commit, preCommit, abort, and finish paths, so independent transactions can
proceed concurrently instead of being serialized by the db write lock.

Key changes in DatabaseTransactionMgr:
- Extract updateTxnLabels from unprotectUpdateInMemoryState (only needed at
  beginTransaction and replay time)
- Convert runningTxnNums from volatile int to AtomicInteger
- Replace ArrayDeque with ConcurrentLinkedDeque for final-status deques
- Replace writeLock/writeUnlock with synchronized(transactionState) in
  preCommitTransaction2PC, commitTransaction, finishTransaction,
  abortTransaction, and abortTransaction2PC

Key changes in PublishVersionDaemon:
- Route publish executor by transactionId instead of dbId when
  enable_per_txn_publish=true (default), enabling intra-DB parallel publish
- Fix race condition: use local variables in tryFinishTxnSync instead of
  shared instance fields for partitionVisibleVersions/backendPartitions
- Rename dbExecutors to publishExecutors

New config flag:
- enable_per_txn_publish: controls publish routing (true=parallel within DB,
  false=sequential per DB fallback). Mutable at runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dataroaring dataroaring force-pushed the database_transaction_lock branch from 49d5051 to db34540 Compare February 7, 2026 21:56
@dataroaring dataroaring changed the title [opt](txn) Reduce lock contention in DatabaseTransactionMgr [opt](txn) Per-transaction locking and parallel publish for DatabaseTransactionMgr Feb 7, 2026
@dataroaring
Copy link
Contributor Author

run buildall

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.

[Enhancement] reduce lock contention in DatabaseTransactionMgr

3 participants