在TiKV MVCC

2016-11-17 伊凡杨 工程

并发控制简介

可串行性是经典的并发方案。它确保执行并发事务的调度与按照某种顺序连续执行事务的调度相同。虽然可序列化性是一个很好的概念,但是很难有效地实现。经典解是两相锁定,即2PL.使用2PL,数据库管理系统(DBMS)维护读和写锁,以确保冲突的事务按照定义良好的顺序执行,或按照可序列化的执行计划执行。然而,锁定有几个缺点。首先,读者和作者相互阻碍。其次,大多数事务是只读的,因此从事务排序的角度来看是无害的。在基于锁定的隔离机制下,可能长时间运行的读事务正在读取的数据对象上不允许有更新事务。因此,更新必须等到读取完成。这严重限制了系统中的并发程度。

多版本并发控制(MVCC)是一个优雅的解决方案解决这个问题,其中每个更新都会创建一个新版本的数据对象而不是更新它,使得并发读者仍然可以在更新事务继续时看到旧版本。这样的策略可以防止只读交易等待。实际上,根本不需要锁定。这是一个非常理想的财产,以及许多数据库系统,如postgreSQL,Oracle和Microsoft SQL Server实现MVCC。

在这篇文章中,我们将探讨TIKV中MVCC实施的复杂性。

在TiKV MVCC

让我们深入TiKV的MVCC实现,它位于src /存储

时间戳甲骨文(TSO)

自从TiKV是分布式存储系统,它需要一个全局唯一的时间服务,称为时间戳oracle.(TSO),以分配一个单调递增的时间戳。类似于谷歌的TrueTime API扳手,这个服务是在TiKV的放置驱动程序(PD)中实现的。每一个TS表示单调递增的时间戳。

存储

要潜入交易部分TiKVsrc /存储是一个很好的起点。存储是一个实际接收Get/Scan命令的结构体。

酒吧结构体存储引擎盒子<引擎>Sendch.SendCh<味精>处理<互斥锁<StorageHandle.>>impl存储酒吧fn开始mut自我配置配置- >结果<>mut处理自我处理打开如果处理处理is_some返回犯错box_err !调度程序已经在运行引擎自我引擎克隆构建器线::构建器::的名字thd_name !“存储调度程序”mut埃尔处理event_loop打开sched_concurrency配置sched_concurrencysched_worker_pool_size配置sched_worker_pool_sizesched_too_busy_threshold配置sched_too_busy_thresholdch自我Sendch.克隆h尝试构建器产卵移动||mut固定播送时间调度器::引擎chsched_concurrencysched_worker_pool_sizesched_too_busy_threshold如果犯错e埃尔运行mut固定播送时间恐慌!“调度程序运行出错:{:?}”e信息!“调度器停止”处理处理一些h好的

开始上面示例中的功能介绍了存储结构的运行方式。

引擎

引擎描述存储系统中实际使用的数据库的特征。它是在raftkvRocksdb_engine.

StorageHandle.

StorageHandle.是处理接收到的命令的结构吗Sendch..I/O由

然后函数就像async_getasync_batch_get在里面贮存Struct将向通道发送相应的命令,调度程序可以获得这些命令并异步执行。

MVCC层被调用进来调度器.存储接收来自客户端的命令,并将命令作为消息发送给调度程序。然后调度程序将处理命令或调用对应的异步函数.有两种类型的操作——读和写。Read在MvccReader,这很容易理解,所以我们不作详细说明。让我们关注编写,这是MVCC实现的核心。

MVCC.

专栏家庭

Percolator通过在特定行中添加额外的列来存储像Lock这样的信息,而TiKV使用RocksDB中的一个列族(CF)来处理所有与Lock相关的信息。具体来说,TiKV存储键值、锁和写入信息CF_DEFAULTCF_LOCK,CF_WRITE

CF的所有值编码如下:

默认的
关键 z {encoded_key} {start_ts (desc)} z {encoded_key} z {encoded_key} {commit_ts (desc)}
价值 {value} {国旗}{primary_key} {start_ts (varint)} {国旗}{start_ts (varint)}

可以找到更多细节这里

事务模型

下面是TiKV事务模型的核心,它是由两阶段提交驱动的MVCC。一个事务中有两个阶段:

  • 腹稿

    1. 事务开始。客户端获取当前时间戳(startTS从TSO)。
    2. 选择一行作为主行,其他行作为辅助行。
    3. 检查这一行上是否有另一个锁或者之后是否有任何提交startTS.这两种情况会导致冲突。如果发生任何一种情况,则提交失败并回滚将被调用。
    4. 锁定主行
    5. 在辅助行上重复上述步骤。
  • 犯罪

    1. 获取提交时间戳commit_ts从TSO。
    2. 检查主行上的锁是否仍然存在。如果锁还在,就继续。如果不是,就回滚。
    3. 写专栏CF_WRITEcommit_ts
    4. 清除相应的主锁。
    5. 在辅助行上重复上述步骤。

垃圾收集器

如果没有,很容易预测,如果没有,则会有更多和更多的MVCC版本垃圾收集器删除无效版本。但是我们不能在安全点之前简单地删除所有版本,因为密钥可能只有一个版本,必须保留它。在TiKV,如果有的话或者删除记录在安全点之前,之后的所有写操作都可以删除;否则只有删除回滚将被删除。

TiKV MVCC.

准备好开始TiDB了吗?