Skip to content

Commit a98b694

Browse files
authored
Remove EXTRA_WRITE strategy in Consensus Commit (#2597)
1 parent beac701 commit a98b694

24 files changed

+171
-1012
lines changed

conf/database.properties

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,6 @@ scalar.db.password=cassandra
1717
# Isolation level used for Consensus Commit. Either `SNAPSHOT` or `SERIALIZABLE` can be specified. The default is `SNAPSHOT`.
1818
#scalar.db.consensus_commit.isolation_level=
1919

20-
# Serializable strategy used for Consensus Commit.
21-
# Either `EXTRA_READ` or `EXTRA_WRITE` can be specified. The default is `EXTRA_READ`.
22-
# If `SNAPSHOT` is specified in the property `scalar.db.consensus_commit.isolation_level`, this is ignored.
23-
#scalar.db.consensus_commit.serializable_strategy=
24-
2520
# The given namespace name will be used by operations that do not already specify a namespace.
2621
# By default, no default namespace name is set on operations.
2722
#scalar.db.default_namespace_name=<a_namespace_name>

core/src/main/java/com/scalar/db/common/error/CoreError.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -458,11 +458,11 @@ public enum CoreError implements ScalarDbError {
458458
""),
459459
CONSENSUS_COMMIT_READING_ALREADY_WRITTEN_DATA_NOT_ALLOWED(
460460
Category.USER_ERROR, "0106", "Reading already-written data is not allowed", "", ""),
461-
CONSENSUS_COMMIT_TRANSACTION_NOT_VALIDATED_IN_EXTRA_READ(
461+
CONSENSUS_COMMIT_TRANSACTION_NOT_VALIDATED_IN_SERIALIZABLE(
462462
Category.USER_ERROR,
463463
"0107",
464464
"The transaction is not validated."
465-
+ " When using the EXTRA_READ serializable strategy, you need to call validate()"
465+
+ " When using the SERIALIZABLE isolation level, you need to call validate()"
466466
+ " before calling commit()",
467467
"",
468468
""),
@@ -929,13 +929,7 @@ public enum CoreError implements ScalarDbError {
929929
"The condition on the column '%s' is not satisfied",
930930
"",
931931
""),
932-
CONSENSUS_COMMIT_READING_EMPTY_RECORDS_IN_EXTRA_WRITE(
933-
Category.CONCURRENCY_ERROR,
934-
"0021",
935-
"Reading empty records might cause a write skew anomaly, so the transaction has been aborted for safety purposes",
936-
"",
937-
""),
938-
CONSENSUS_COMMIT_ANTI_DEPENDENCY_FOUND_IN_EXTRA_READ(
932+
CONSENSUS_COMMIT_ANTI_DEPENDENCY_FOUND(
939933
Category.CONCURRENCY_ERROR,
940934
"0022",
941935
"An anti-dependency was found. The transaction has been aborted",

core/src/main/java/com/scalar/db/transaction/consensuscommit/CommitHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ private void prepareRecords(Snapshot snapshot)
205205

206206
public void validate(Snapshot snapshot) throws ValidationException {
207207
try {
208-
// validation is executed when SERIALIZABLE with EXTRA_READ strategy is chosen.
209-
snapshot.toSerializableWithExtraRead(storage);
208+
// validation is executed when SERIALIZABLE is chosen.
209+
snapshot.toSerializable(storage);
210210
} catch (ExecutionException e) {
211211
throw new ValidationException(
212212
CoreError.CONSENSUS_COMMIT_VALIDATION_FAILED.buildMessage(), e, snapshot.getId());

core/src/main/java/com/scalar/db/transaction/consensuscommit/CommitMutationComposer.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import com.scalar.db.api.Consistency;
1212
import com.scalar.db.api.Delete;
1313
import com.scalar.db.api.DeleteIf;
14-
import com.scalar.db.api.Get;
1514
import com.scalar.db.api.Mutation;
1615
import com.scalar.db.api.Operation;
1716
import com.scalar.db.api.Put;
@@ -65,9 +64,8 @@ private void add(Delete base, @Nullable TransactionResult result) throws Executi
6564

6665
private void add(Selection base, @Nullable TransactionResult result) throws ExecutionException {
6766
if (result == null) {
68-
// for deleting non-existing record that was prepared with DELETED for Serializable with
69-
// Extra-write
70-
mutations.add(composeDelete(base, null));
67+
throw new AssertionError(
68+
"This path should not be reached since the EXTRA_WRITE strategy is deleted");
7169
} else if (result.getState().equals(TransactionState.PREPARED)) {
7270
// for rollforward in lazy recovery
7371
mutations.add(composePut(base, result));
@@ -122,10 +120,8 @@ private Key getPartitionKey(Operation base, @Nullable TransactionResult result)
122120
TransactionTableMetadata metadata = tableMetadataManager.getTransactionTableMetadata(base);
123121
return ScalarDbUtils.getPartitionKey(result, metadata.getTableMetadata());
124122
} else {
125-
// for deleting non-existing record that was prepared with DELETED for Serializable with
126-
// Extra-write
127-
assert base instanceof Get;
128-
return base.getPartitionKey();
123+
throw new AssertionError(
124+
"This path should not be reached since the EXTRA_WRITE strategy is deleted");
129125
}
130126
}
131127
}
@@ -142,10 +138,8 @@ private Optional<Key> getClusteringKey(Operation base, @Nullable TransactionResu
142138
TransactionTableMetadata metadata = tableMetadataManager.getTransactionTableMetadata(base);
143139
return ScalarDbUtils.getClusteringKey(result, metadata.getTableMetadata());
144140
} else {
145-
// for deleting non-existing record that was prepared with DELETED for Serializable with
146-
// Extra-write
147-
assert base instanceof Get;
148-
return base.getClusteringKey();
141+
throw new AssertionError(
142+
"This path should not be reached since the EXTRA_WRITE strategy is deleted");
149143
}
150144
}
151145
}

core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitConfig.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public class ConsensusCommitConfig {
2222
public static final String TRANSACTION_MANAGER_NAME = "consensus-commit";
2323
public static final String PREFIX = DatabaseConfig.PREFIX + "consensus_commit.";
2424
public static final String ISOLATION_LEVEL = PREFIX + "isolation_level";
25-
public static final String SERIALIZABLE_STRATEGY = PREFIX + "serializable_strategy";
2625
public static final String COORDINATOR_NAMESPACE = PREFIX + "coordinator.namespace";
2726

2827
public static final String PARALLEL_EXECUTOR_COUNT = PREFIX + "parallel_executor_count";
@@ -64,7 +63,6 @@ public class ConsensusCommitConfig {
6463
public static final int DEFAULT_COORDINATOR_GROUP_COMMIT_TIMEOUT_CHECK_INTERVAL_MILLIS = 20;
6564

6665
private final Isolation isolation;
67-
private final SerializableStrategy strategy;
6866
@Nullable private final String coordinatorNamespace;
6967

7068
private final int parallelExecutorCount;
@@ -113,14 +111,16 @@ public ConsensusCommitConfig(DatabaseConfig databaseConfig) {
113111
.toUpperCase(Locale.ROOT));
114112
if (isolation.equals(Isolation.SERIALIZABLE)) {
115113
validateCrossPartitionScanConfig(databaseConfig);
114+
115+
if (databaseConfig
116+
.getProperties()
117+
.containsKey("scalar.db.consensus_commit.serializable_strategy")) {
118+
logger.warn(
119+
"The property \"scalar.db.consensus_commit.serializable_strategy\" is deprecated and will "
120+
+ "be removed in 5.0.0. The EXTRA_READ strategy is always used for the SERIALIZABLE "
121+
+ "isolation level.");
122+
}
116123
}
117-
strategy =
118-
SerializableStrategy.valueOf(
119-
getString(
120-
databaseConfig.getProperties(),
121-
SERIALIZABLE_STRATEGY,
122-
SerializableStrategy.EXTRA_READ.toString())
123-
.toUpperCase(Locale.ROOT));
124124

125125
coordinatorNamespace = getString(databaseConfig.getProperties(), COORDINATOR_NAMESPACE, null);
126126

@@ -193,10 +193,6 @@ public Isolation getIsolation() {
193193
return isolation;
194194
}
195195

196-
public SerializableStrategy getSerializableStrategy() {
197-
return strategy;
198-
}
199-
200196
public Optional<String> getCoordinatorNamespace() {
201197
return Optional.ofNullable(coordinatorNamespace);
202198
}

core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitManager.java

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -134,49 +134,49 @@ private CommitHandler createCommitHandler() {
134134

135135
@Override
136136
public DistributedTransaction begin() {
137-
return begin(config.getIsolation(), config.getSerializableStrategy());
137+
return begin(config.getIsolation());
138138
}
139139

140140
@Override
141141
public DistributedTransaction begin(String txId) {
142-
return begin(txId, config.getIsolation(), config.getSerializableStrategy());
142+
return begin(txId, config.getIsolation());
143143
}
144144

145145
/** @deprecated As of release 2.4.0. Will be removed in release 4.0.0. */
146146
@Deprecated
147147
@Override
148148
public DistributedTransaction start(com.scalar.db.api.Isolation isolation) {
149-
return begin(Isolation.valueOf(isolation.name()), config.getSerializableStrategy());
149+
return begin(Isolation.valueOf(isolation.name()));
150150
}
151151

152152
/** @deprecated As of release 2.4.0. Will be removed in release 4.0.0. */
153153
@Deprecated
154154
@Override
155155
public DistributedTransaction start(String txId, com.scalar.db.api.Isolation isolation) {
156-
return begin(txId, Isolation.valueOf(isolation.name()), config.getSerializableStrategy());
156+
return begin(txId, Isolation.valueOf(isolation.name()));
157157
}
158158

159159
/** @deprecated As of release 2.4.0. Will be removed in release 4.0.0. */
160160
@Deprecated
161161
@Override
162162
public DistributedTransaction start(
163163
com.scalar.db.api.Isolation isolation, com.scalar.db.api.SerializableStrategy strategy) {
164-
return begin(Isolation.valueOf(isolation.name()), (SerializableStrategy) strategy);
164+
return begin(Isolation.valueOf(isolation.name()));
165165
}
166166

167167
/** @deprecated As of release 2.4.0. Will be removed in release 4.0.0. */
168168
@Deprecated
169169
@Override
170170
public DistributedTransaction start(com.scalar.db.api.SerializableStrategy strategy) {
171-
return begin(Isolation.SERIALIZABLE, (SerializableStrategy) strategy);
171+
return begin(Isolation.SERIALIZABLE);
172172
}
173173

174174
/** @deprecated As of release 2.4.0. Will be removed in release 4.0.0. */
175175
@Deprecated
176176
@Override
177177
public DistributedTransaction start(
178178
String txId, com.scalar.db.api.SerializableStrategy strategy) {
179-
return begin(txId, Isolation.SERIALIZABLE, (SerializableStrategy) strategy);
179+
return begin(txId, Isolation.SERIALIZABLE);
180180
}
181181

182182
/** @deprecated As of release 2.4.0. Will be removed in release 4.0.0. */
@@ -186,31 +186,29 @@ public DistributedTransaction start(
186186
String txId,
187187
com.scalar.db.api.Isolation isolation,
188188
com.scalar.db.api.SerializableStrategy strategy) {
189-
return begin(txId, Isolation.valueOf(isolation.name()), (SerializableStrategy) strategy);
189+
return begin(txId, Isolation.valueOf(isolation.name()));
190190
}
191191

192192
@VisibleForTesting
193-
DistributedTransaction begin(Isolation isolation, SerializableStrategy strategy) {
193+
DistributedTransaction begin(Isolation isolation) {
194194
String txId = UUID.randomUUID().toString();
195-
return begin(txId, isolation, strategy);
195+
return begin(txId, isolation);
196196
}
197197

198198
@VisibleForTesting
199-
DistributedTransaction begin(String txId, Isolation isolation, SerializableStrategy strategy) {
199+
DistributedTransaction begin(String txId, Isolation isolation) {
200200
checkArgument(!Strings.isNullOrEmpty(txId));
201201
checkNotNull(isolation);
202202
if (isGroupCommitEnabled()) {
203203
assert groupCommitter != null;
204204
txId = groupCommitter.reserve(txId);
205205
}
206-
if (!config.getIsolation().equals(isolation)
207-
|| !config.getSerializableStrategy().equals(strategy)) {
206+
if (!config.getIsolation().equals(isolation)) {
208207
logger.warn(
209-
"Setting different isolation level or serializable strategy from the ones "
210-
+ "in DatabaseConfig might cause unexpected anomalies");
208+
"Setting different isolation level from the one in DatabaseConfig might cause unexpected "
209+
+ "anomalies");
211210
}
212-
Snapshot snapshot =
213-
new Snapshot(txId, isolation, strategy, tableMetadataManager, parallelExecutor);
211+
Snapshot snapshot = new Snapshot(txId, isolation, tableMetadataManager, parallelExecutor);
214212
CrudHandler crud =
215213
new CrudHandler(
216214
storage, snapshot, tableMetadataManager, isIncludeMetadataEnabled, parallelExecutor);

core/src/main/java/com/scalar/db/transaction/consensuscommit/PrepareMutationComposer.java

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
import com.scalar.db.api.Operation;
1515
import com.scalar.db.api.Put;
1616
import com.scalar.db.api.PutBuilder;
17-
import com.scalar.db.api.PutIfNotExists;
1817
import com.scalar.db.api.TransactionState;
1918
import com.scalar.db.exception.storage.ExecutionException;
2019
import com.scalar.db.io.Column;
2120
import com.scalar.db.io.IntColumn;
22-
import com.scalar.db.io.Value;
2321
import java.util.ArrayList;
2422
import java.util.List;
2523
import javax.annotation.Nullable;
@@ -45,7 +43,8 @@ public void add(Operation base, @Nullable TransactionResult result) throws Execu
4543
} else if (base instanceof Delete) {
4644
add((Delete) base, result);
4745
} else if (base instanceof Get) {
48-
add((Get) base);
46+
throw new AssertionError(
47+
"This path should not be reached since the EXTRA_WRITE strategy is deleted");
4948
} else {
5049
throw new AssertionError("PrepareMutationComposer.add only accepts Put, Delete, or Get");
5150
}
@@ -133,28 +132,6 @@ private void add(Delete base, @Nullable TransactionResult result) throws Executi
133132
mutations.add(putBuilder.build());
134133
}
135134

136-
// This prepares a record that was read but didn't exist to avoid anti-dependency for the record.
137-
// This is only called when Serializable with Extra-write strategy is enabled.
138-
private void add(Get base) {
139-
Put put =
140-
new Put(base.getPartitionKey(), base.getClusteringKey().orElse(null))
141-
.forNamespace(base.forNamespace().get())
142-
.forTable(base.forTable().get())
143-
.withConsistency(Consistency.LINEARIZABLE);
144-
145-
List<Value<?>> values = new ArrayList<>();
146-
values.add(Attribute.toIdValue(id));
147-
values.add(Attribute.toStateValue(TransactionState.DELETED));
148-
values.add(Attribute.toPreparedAtValue(current));
149-
values.add(Attribute.toVersionValue(1));
150-
151-
// check if the record is not interrupted by other conflicting transactions
152-
put.withCondition(new PutIfNotExists());
153-
154-
put.withValues(values);
155-
mutations.add(put);
156-
}
157-
158135
private List<Column<?>> createBeforeColumns(Mutation base, TransactionResult result)
159136
throws ExecutionException {
160137
List<Column<?>> columns = new ArrayList<>();

core/src/main/java/com/scalar/db/transaction/consensuscommit/RollbackMutationComposer.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,8 @@ private Optional<TransactionResult> getLatestResult(
156156
clusteringKey =
157157
ScalarDbUtils.getClusteringKey(result, metadata.getTableMetadata()).orElse(null);
158158
} else {
159-
// for deleting non-existing record that was prepared with DELETED for Serializable with
160-
// Extra-write
161-
assert operation instanceof Get;
162-
partitionKey = operation.getPartitionKey();
163-
clusteringKey = operation.getClusteringKey().orElse(null);
159+
throw new AssertionError(
160+
"This path should not be reached since the EXTRA_WRITE strategy is deleted");
164161
}
165162
}
166163

core/src/main/java/com/scalar/db/transaction/consensuscommit/SerializableStrategy.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
* A Serializable strategy used in Consensus Commit algorithm. Both strategies basically make
77
* transactions avoid an anti-dependency that is the root cause of the anomalies in Snapshot
88
* Isolation.
9+
*
10+
* @deprecated As of release 3.16.0. Will be removed in release 5.0.0
911
*/
1012
@SuppressFBWarnings("NM_SAME_SIMPLE_NAME_AS_INTERFACE")
13+
@Deprecated
1114
public enum SerializableStrategy implements com.scalar.db.api.SerializableStrategy {
1215
/**
1316
* Extra-write strategy converts all read set into write set when preparing records to remove

0 commit comments

Comments
 (0)