@@ -36,6 +36,7 @@ public class CommitHandler {
3636 protected final Coordinator coordinator ;
3737 private final TransactionTableMetadataManager tableMetadataManager ;
3838 private final ParallelExecutor parallelExecutor ;
39+ protected final boolean coordinatorWriteOmissionOnReadOnlyEnabled ;
3940
4041 @ LazyInit @ Nullable private BeforePreparationSnapshotHook beforePreparationSnapshotHook ;
4142
@@ -44,11 +45,13 @@ public CommitHandler(
4445 DistributedStorage storage ,
4546 Coordinator coordinator ,
4647 TransactionTableMetadataManager tableMetadataManager ,
47- ParallelExecutor parallelExecutor ) {
48+ ParallelExecutor parallelExecutor ,
49+ boolean coordinatorWriteOmissionOnReadOnlyEnabled ) {
4850 this .storage = checkNotNull (storage );
4951 this .coordinator = checkNotNull (coordinator );
5052 this .tableMetadataManager = checkNotNull (tableMetadataManager );
5153 this .parallelExecutor = checkNotNull (parallelExecutor );
54+ this .coordinatorWriteOmissionOnReadOnlyEnabled = coordinatorWriteOmissionOnReadOnlyEnabled ;
5255 }
5356
5457 /**
@@ -106,42 +109,62 @@ private void waitBeforePreparationSnapshotHookFuture(
106109 }
107110 }
108111
109- public void commit (Snapshot snapshot ) throws CommitException , UnknownTransactionStatusException {
112+ public void commit (Snapshot snapshot , boolean readOnly )
113+ throws CommitException , UnknownTransactionStatusException {
114+ boolean hasWritesOrDeletesInSnapshot = !readOnly && snapshot .hasWritesOrDeletes ();
115+
110116 Optional <Future <Void >> snapshotHookFuture = invokeBeforePreparationSnapshotHook (snapshot );
111- try {
112- prepare (snapshot );
113- } catch (PreparationException e ) {
114- safelyCallOnFailureBeforeCommit (snapshot );
115- abortState (snapshot .getId ());
116- rollbackRecords (snapshot );
117- if (e instanceof PreparationConflictException ) {
118- throw new CommitConflictException (e .getMessage (), e , e .getTransactionId ().orElse (null ));
117+
118+ if (hasWritesOrDeletesInSnapshot ) {
119+ try {
120+ prepare (snapshot );
121+ } catch (PreparationException e ) {
122+ safelyCallOnFailureBeforeCommit (snapshot );
123+ abortState (snapshot .getId ());
124+ rollbackRecords (snapshot );
125+ if (e instanceof PreparationConflictException ) {
126+ throw new CommitConflictException (e .getMessage (), e , e .getTransactionId ().orElse (null ));
127+ }
128+ throw new CommitException (e .getMessage (), e , e .getTransactionId ().orElse (null ));
129+ } catch (Exception e ) {
130+ safelyCallOnFailureBeforeCommit (snapshot );
131+ throw e ;
119132 }
120- throw new CommitException (e .getMessage (), e , e .getTransactionId ().orElse (null ));
121- } catch (Exception e ) {
122- safelyCallOnFailureBeforeCommit (snapshot );
123- throw e ;
124133 }
125134
126- try {
127- validate (snapshot );
128- } catch (ValidationException e ) {
129- safelyCallOnFailureBeforeCommit (snapshot );
130- abortState (snapshot .getId ());
131- rollbackRecords (snapshot );
132- if (e instanceof ValidationConflictException ) {
133- throw new CommitConflictException (e .getMessage (), e , e .getTransactionId ().orElse (null ));
135+ if (snapshot .hasReads ()) {
136+ try {
137+ validate (snapshot );
138+ } catch (ValidationException e ) {
139+ safelyCallOnFailureBeforeCommit (snapshot );
140+
141+ // If the transaction has no writes and deletes, we don't need to abort-state and
142+ // rollback-records since there are no changes to be made.
143+ if (hasWritesOrDeletesInSnapshot || !coordinatorWriteOmissionOnReadOnlyEnabled ) {
144+ abortState (snapshot .getId ());
145+ }
146+ if (hasWritesOrDeletesInSnapshot ) {
147+ rollbackRecords (snapshot );
148+ }
149+
150+ if (e instanceof ValidationConflictException ) {
151+ throw new CommitConflictException (e .getMessage (), e , e .getTransactionId ().orElse (null ));
152+ }
153+ throw new CommitException (e .getMessage (), e , e .getTransactionId ().orElse (null ));
154+ } catch (Exception e ) {
155+ safelyCallOnFailureBeforeCommit (snapshot );
156+ throw e ;
134157 }
135- throw new CommitException (e .getMessage (), e , e .getTransactionId ().orElse (null ));
136- } catch (Exception e ) {
137- safelyCallOnFailureBeforeCommit (snapshot );
138- throw e ;
139158 }
140159
141160 waitBeforePreparationSnapshotHookFuture (snapshot , snapshotHookFuture .orElse (null ));
142161
143- commitState (snapshot );
144- commitRecords (snapshot );
162+ if (hasWritesOrDeletesInSnapshot || !coordinatorWriteOmissionOnReadOnlyEnabled ) {
163+ commitState (snapshot );
164+ }
165+ if (hasWritesOrDeletesInSnapshot ) {
166+ commitRecords (snapshot );
167+ }
145168 }
146169
147170 protected void handleCommitConflict (Snapshot snapshot , Exception cause )
0 commit comments