Enum ConflictHandler

    • Enum Constant Detail

      • IGNORE_ALL

        public static final ConflictHandler IGNORE_ALL
        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.
      • RETRY_ON_WRITE_WRITE

        public static final ConflictHandler RETRY_ON_WRITE_WRITE
        If two transactions concurrently write to the same cell the one that commits later will throw a TransactionConflictException and should have details about how this happened.
      • RETRY_ON_VALUE_CHANGED

        public static final ConflictHandler RETRY_ON_VALUE_CHANGED
        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 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.

      • SERIALIZABLE

        public static final ConflictHandler SERIALIZABLE
        This conflict type does everything that 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.

      • RETRY_ON_WRITE_WRITE_CELL

        public static final ConflictHandler RETRY_ON_WRITE_WRITE_CELL
        Same as 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.
      • SERIALIZABLE_CELL

        public static final ConflictHandler SERIALIZABLE_CELL
        Same as 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_INDEX

        public static final ConflictHandler SERIALIZABLE_INDEX
        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_LOCK_LEVEL_MIGRATION

        public static final ConflictHandler SERIALIZABLE_LOCK_LEVEL_MIGRATION
        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.

      • RETRY_ON_WRITE_WRITE_MIGRATION

        public static final ConflictHandler RETRY_ON_WRITE_WRITE_MIGRATION
        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.

    • Method Detail

      • values

        public static ConflictHandler[] values()
        Returns an array containing the constants of this enum type, in the order they are declared. This method may be used to iterate over the constants as follows:
        for (ConflictHandler c : ConflictHandler.values())
            System.out.println(c);
        
        Returns:
        an array containing the constants of this enum type, in the order they are declared
      • valueOf

        public static ConflictHandler valueOf​(String name)
        Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
        Parameters:
        name - the name of the enum constant to be returned.
        Returns:
        the enum constant with the specified name
        Throws:
        IllegalArgumentException - if this enum type has no constant with the specified name
        NullPointerException - if the argument is null
      • lockCellsForConflicts

        public boolean lockCellsForConflicts()
      • lockRowsForConflicts

        public boolean lockRowsForConflicts()
      • checkWriteWriteConflicts

        public boolean checkWriteWriteConflicts()
      • checkReadWriteConflicts

        public boolean checkReadWriteConflicts()