Struct txn_types::Write[][src]

pub struct Write {
    pub write_type: WriteType,
    pub start_ts: TimeStamp,
    pub short_value: Option<Value>,
    pub has_overlapped_rollback: bool,
    pub gc_fence: Option<TimeStamp>,
}

Fields

write_type: WriteTypestart_ts: TimeStampshort_value: Option<Value>has_overlapped_rollback: bool

The commit_ts of transactions can be non-globally-unique. But since we store Rollback records in the same CF where Commit records is, and Rollback records are saved with user_key{start_ts} as the internal key, the collision between Commit and Rollback records can’t be avoided. In this case, we keep the Commit record, and set the has_overlapped_rollback flag to indicate that there’s also a Rollback record. Also note that has_overlapped_rollback field is only necessary when the Rollback record should be protected.

gc_fence: Option<TimeStamp>

Records the next version after this version when overlapping rollback happens on an already existed commit record.

When a rollback flag is written on an already-written commit record, it causes rewriting the commit record. It may cause problems with the GC compaction filter. Consider this case:

Key_100_put, Key_120_del

and a rollback on 100 happens:

Key_100_put_R, Key_120_del

Then GC with safepoint = 130 may happen. However a follower may not have finished applying the change. So on the follower, it’s possible that:

  1. Key_100_put, Key_120_del applied
  2. GC with safepoint = 130 started and Key_100_put, Key_120_del are deleted
  3. Finished applying Key_100_put_R, which means to rewrite Key_100_put
  4. Read at 140 should get nothing (since it’s MVCC-deleted at 120) but finds Key_100_put

To solve the problem, when marking has_overlapped_rollback on an already-existed commit record, add a special field gc_fence on it. If there is a newer version after the record being rewritten, the next version’s commit_ts will be recorded. When MVCC reading finds a commit record with a GC fence timestamp but the corresponding version that matches that ts doesn’t exist, the current version will be believed to be already GC-ed and ignored.

Therefore, for the example above, in the 3rd step it will record the version 120 to the gc_fence field:

Key_100_put_R_120, Key_120_del

And when the reading in the 4th step finds the PUT record but the version at 120 doesn’t exist, it will be regarded as already GC-ed and ignored.

For CDC and TiFlash, when they receives a commit record with gc_fence field set, it can determine that it must be caused by an overlapped rollback instead of an actual commit.

Note: GC fence will only be written on PUT and DELETE versions, and may only point to a PUT or DELETE version. If there are other Lock and Rollback records after the record that’s being rewritten, they will be skipped. For example, in this case:

Key_100_put, Key_105_lock, Key_110_rollback, Key_120_del

If overlapped rollback happens at 100, the Key_100_put will be rewritten as Key_100_put_R_120. It points to version 120 instead of the nearest 105.

The meaning of the field:

Implementations

impl Write[src]

pub fn new(
    write_type: WriteType,
    start_ts: TimeStamp,
    short_value: Option<Value>
) -> Write
[src]

Creates a new Write record.

pub fn new_rollback(start_ts: TimeStamp, protected: bool) -> Write[src]

pub fn set_overlapped_rollback(
    self,
    has_overlapped_rollback: bool,
    gc_fence: Option<TimeStamp>
) -> Self
[src]

pub fn parse_type(b: &[u8]) -> Result<WriteType>[src]

pub fn as_ref(&self) -> WriteRef<'_>[src]

Trait Implementations

impl Clone for Write[src]

impl Debug for Write[src]

impl PartialEq<Write> for Write[src]

impl StructuralPartialEq for Write[src]

Auto Trait Implementations

impl RefUnwindSafe for Write

impl Send for Write

impl Sync for Write

impl Unpin for Write

impl UnwindSafe for Write

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T[src]

type Init = T

The type for initializers.

impl<T> Same<T> for T[src]

type Output = T

Should always be Self

impl<T> Sealed<T> for T where
    T: ?Sized
[src]

impl<T> SendSyncUnwindSafe for T where
    T: Send + Sync + UnwindSafe + ?Sized
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 
[src]