All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.palantir.atlasdb.transaction.api.ConflictHandler Maven / Gradle / Ivy

There is a newer version: 0.1152.0
Show newest version
/*
 * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.palantir.atlasdb.transaction.api;

public enum ConflictHandler {
    /**
     * If two transactions concurrently write to the same cell the one that has started later will win.  We
     * are ignoring write conflicts in this case.
     */
    IGNORE_ALL(false, false, false, false),

    /**
     * If two transactions concurrently write to the same cell the one that commits later will
     * throw a {@link TransactionConflictException} and should have details about how this happened.
     */
    RETRY_ON_WRITE_WRITE(false, true, true, false),

    /**
     * If a transaction writes a new value to a Cell (different than the value read by that
     * transaction), then it will throw if another concurrent transaction wrote to this cell
     * concurrently and committed first.
     * 

* If a transaction is writing the same value to a Cell (same as was read by that transaction), * then it will throw in the case where a concurrent transaction has written a different * value to this Cell. A concurrent transaction that just writes the same value will not cause * throwing of a {@link TransactionConflictException}, because we want to allow many * transactions to do touches concurrently, but they should conflict with a change to this cell. *

* Note: Transactions that only touch a cell still need to grab a write lock for it during commit. * For a cell that is frequently touched and infrequently updated (i.e., a read-write lock design * with mostly reads), it may make sense to replicate the cell, have each reader touch one * replica, and have writers update all replicas. *

* Note: This ConflictHandler has the ABA problem (https://en.wikipedia.org/wiki/ABA_problem). The easiest * way to fix this is to have the value always increase. */ RETRY_ON_VALUE_CHANGED(false, true, true, false), /** * This conflict type does everything that {@link #RETRY_ON_WRITE_WRITE} does but additionally detects * and retries on read/write conflict. *

* A read/write conflict happens whenever you read a value but a concurrent transaction has written a * new differing value and committed before your transaction commits. This logic only applies to write * transactions. Read transactions are already serializable because they read from a consistent point in time. *

* This should not be used on tables that are expected to have tons of reads because we must keep the whole read * set in memory so we can compare it at commit time to ensure that everything we read has not changed. */ SERIALIZABLE(false, true, true, true), /** * Same as {@link RETRY_ON_WRITE_WRITE}, but checks for conflicts by locking cells during commit instead * of locking rows. Cell locks are more fine-grained, so this will produce less contention at the expense * of requiring more locks to be acquired. */ RETRY_ON_WRITE_WRITE_CELL(true, false, true, false), /** * Same as {@link SERIALIZABLE}, but checks for conflicts by locking cells during commit instead * of locking rows. Cell locks are more fine-grained, so this will produce less contention at the expense * of requiring more locks to be acquired. */ SERIALIZABLE_CELL(true, false, true, true), /** * This conflict handler is designed to be used by index tables. As any write/write conflict on an index table * will necessarily also be a write/write conflict on base table, we do not need to check write/write conflicts * on index tables. Read/write conflicts should still need to be checked, since we do not need to read the index * table with the main table. *

* This conflict does not lock, because it's assumed that a semantically equivalent lock is taken out on * the base table. */ SERIALIZABLE_INDEX(false, false, false, true), /** * This conflict handler is designed to be used for migrating a table from SERIALIZABLE to SERIALIZABLE_CELL or * SERIALIZABLE_INDEX conflict handler, or vice versa without requiring a simultaneous shutdown of all clients. *

* Migration should be handled in two steps. First all the nodes should migrate to SERIALIZABLE_LOCK_LEVEL_MIGRATION * with a rolling upgrade. Once this is complete, then in the second step migration to target conflict handler from * SERIALIZABLE_LOCK_LEVEL_MIGRATION can be performed, in a rolling fashion. *

* Current implementation of lock service permits a client to lock a cell after locking the row that cell * belongs to. In a scenario where we migrate table A to SERIALIZABLE_CELL from SERIALIZABLE, and conduct a rolling * upgrade, if client_1 is on the newer version, it will try to acquire cell locks for its transaction t1; while * client_2 with an older version, acquiring row locks for its transaction t2. If t1 and t2 are modifying the same * cell then correctness issues may occur as there is no way for t1 to be aware of t2. Locking on both cell and row * level prevents this issue. */ SERIALIZABLE_LOCK_LEVEL_MIGRATION(true, true, true, true), /** * This conflict handler is analogous to SERIALIZABLE_LOCK_LEVEL_MIGRATION, but for migrating between * RETRY_ON_WRITE_WRITE and RETRY_ON_WRITE_WRITE_CELL. *

* Migrations between RETRY_ON_WRITE_WRITE (ROWW) and RETRY_ON_WRITE_WRITE_CELL (ROWWC) using * RETRY_ON_WRITE_WRITE_MIGRATION (ROWWM) takes three steps: * 0. Product is on version V0, and schema version SV0, and does not even know about ROWWM. * 1. Upgrade product to V1, supporting schema version SV1 (not supporting downgrades to SV0), and now knows * about ROWWM (but does *not* use it). * 2. Upgrade product to V2, supporting SV2 (supporting downgrades to SV1), and uses ROWWM. * 3. Upgrade product to V3, supporting SV3 (supporting downgrades to SV2 but not SV1), and uses the desired new * strategy * (for example, now using ROWWC where it was using ROWW in version v0). *

* Failure to adhere to this flow may cause arbitrary data corruption. * */ RETRY_ON_WRITE_WRITE_MIGRATION(true, true, true, false); private final boolean lockCellsForConflicts; private final boolean lockRowsForConflicts; private final boolean checkWriteWriteConflicts; private final boolean checkReadWriteConflicts; ConflictHandler( boolean lockCellsForConflicts, boolean lockRowsForConflicts, boolean checkWriteWriteConflicts, boolean checkReadWriteConflicts) { this.lockCellsForConflicts = lockCellsForConflicts; this.lockRowsForConflicts = lockRowsForConflicts; this.checkWriteWriteConflicts = checkWriteWriteConflicts; this.checkReadWriteConflicts = checkReadWriteConflicts; } public boolean lockCellsForConflicts() { return lockCellsForConflicts; } public boolean lockRowsForConflicts() { return lockRowsForConflicts; } public boolean checkWriteWriteConflicts() { return checkWriteWriteConflicts; } public boolean checkReadWriteConflicts() { return checkReadWriteConflicts; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy