Struct txn_types::write::Write [−][src]
Fields
write_type: WriteType
start_ts: TimeStamp
short_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:
Key_100_put
,Key_120_del
applied- GC with safepoint = 130 started and
Key_100_put
,Key_120_del
are deleted - Finished applying
Key_100_put_R
, which means to rewriteKey_100_put
- Read at
140
should get nothing (since it’s MVCC-deleted at 120) but findsKey_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:
None
: A record that haven’t been rewrittenSome(0)
: A commit record that has been rewritten due to overlapping rollback, but it doesn’t have an newer version.Some(ts)
: A commit record that has been rewritten due to overlapping rollback, and it’s next version’scommit_ts
ists
Implementations
impl Write
[src]
pub fn new(
write_type: WriteType,
start_ts: TimeStamp,
short_value: Option<Value>
) -> Write
[src]
write_type: WriteType,
start_ts: TimeStamp,
short_value: Option<Value>
) -> Write
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]
self,
has_overlapped_rollback: bool,
gc_fence: Option<TimeStamp>
) -> Self
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]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T> Instrument for T
[src]
pub fn instrument(self, span: Span) -> Instrumented<Self>
[src]
pub fn in_current_span(self) -> Instrumented<Self>
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> Pointable for T
[src]
pub const ALIGN: usize
[src]
type Init = T
The type for initializers.
pub unsafe fn init(init: <T as Pointable>::Init) -> usize
[src]
pub unsafe fn deref<'a>(ptr: usize) -> &'a T
[src]
pub unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T
[src]
pub unsafe fn drop(ptr: usize)
[src]
impl<T> Same<T> for T
[src]
type Output = T
Should always be Self
impl<T> Sealed<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> SendSyncUnwindSafe for T where
T: Send + Sync + UnwindSafe + ?Sized,
[src]
T: Send + Sync + UnwindSafe + ?Sized,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
pub fn to_owned(&self) -> T
[src]
pub fn clone_into(&self, target: &mut T)
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
pub fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<V, T> VZip<V> for T where
V: MultiLane<T>,
[src]
V: MultiLane<T>,