004、体系结构之TiKV分布式事务
数据找到并且修改后。此时提交事务(commit)的时候。此时就进入两阶段prewrite - commit提交的第一阶段会用三个CF 来存放这些数据信息。一类列簇对应一类键值对 第一个CF(default)存放的是数据 的键值对。第二个存放的是锁信息。 存放事务信息给数据加锁其他事务不能访问第三个对应的是提交信息。(主键3这一行的开始提交时间100提交完成时间110)put3_100,Frank 3_100: primary_tso 表示是在事务时间戳100的时候对3这个主键进行修改。 注意增删改的操作里面放的都是新数据。包括删除要理解这张图里的 TiDB 分布式事务我们结合 TiKV 的列族CF和 MVCC多版本并发控制机制拆解事务的开始begin、预写prewrite、提交commit三个阶段TiDB 是分布式数据库数据存储在 TiKV基于 RocksDB中。TiKV 通过 列族CF 管理不同维度的数据DefaultCF存储用户数据的实际键值对如 put3_100, Frank表示键 3_100对应值 Frank其中100是事务的开始时间戳start_ts。 LockCF存储事务的锁信息防止并发修改冲突如 prewrite时加锁commit后解锁。 WriteCF存储事务的提交信息如 commit_ts与 start_ts的映射标记版本可见性。事务执行三阶段结合图中流程图中事务的操作是Begin; 3, xxx - 3, Frank; Commit;我们分三个阶段分析Begin获取开始时间戳start_ts事务开始时TiDB 向 PDPlacement Driver集群元数据管理 申请一个单调递增的时间戳作为 start_ts图中 start timestamp 100。此时事务进入“活跃”状态准备修改数据但还未真正写入仅标记事务开始。Prewrite预写数据 加锁确保原子性与并发安全事务执行写操作如 update 3 set xxxFrankTiKV 会执行 prewrite 流程将数据修改和锁信息写入不同 CFDefault CF写入“带时间戳的键值对”如put 3_100, Frank。这里 3_100是键3是主键100是 start_tsFrank是新值。Default存储的是未提交的“写前版本”因为事务还没提交其他事务不能直接看到。Lock CF写入锁记录如3, (W, pk, 3, 100 ...)。W表示是写锁防止其他事务修改同一行pk3是主键标记锁对应的行100是 start_ts标记锁所属的事务。锁的作用是防止并发事务同时修改同一行保证事务的原子性要么全成功要么全失败。Write CF此时暂不写入因为事务还没提交commit_ts未生成。Commit获取提交时间戳commit_ts 提交数据 解锁事务执行 Commit时TiKV 执行 commit 流程获取 commit_ts向 PD 申请一个比 start_ts大的时间戳作为 commit_ts图中 commit timestamp 110。Write CF写入提交信息如put 3_110, 100。这里 3_110是键3是主键110是 commit_ts100是 start_ts。这条记录的含义是主键 3在 commit_ts110时版本 start_ts100的数据被提交。Lock CF删除锁记录或写入解锁标记图中显示为3, (D, pk, 3, 100 ...)。D表示“删除锁”或解锁因为事务已提交锁不再需要其他事务可以正常访问/修改这行数据。Default CF保留之前的put 3_100, FrankMVCC 会保留历史版本供后续读操作按时间戳可见性读取。最终效果多版本并发控制MVCC事务提交后TiKV 中存储了多版本数据DefaultCFput 3_100, Frank未提交的写前版本被 start_ts100标记。WriteCFput 3_110, 100提交信息标记 start_ts100的版本在 commit_ts110时可见。LockCF无锁记录事务已提交锁已释放。当其他事务读取主键 3时TiDB 会根据读取时间戳read_ts和 MVCC 规则判断可见性如果 read_ts ≥ 110则能看到 Frank因为 commit_ts110表示该版本已提交且对 read_ts≥110的事务可见如果 100 ≤ read_ts 110则看不到 Frank因为事务未提交锁存在如果 read_ts 100则看到旧版本如果有的话。注意 整个分布事务中只在第一行加锁或者说主锁也就是pk。事务相关的信息也会记录到TiKV 中持久化。如果要读取id3的数据会先到write这个聚簇中查看put 3_110, 100可以看到最近一次事务时110提交开始是100然后找3_100的default把相应数据找到。begin1,Tom - 1,Jack2,Andy - 2,CandyCommit;问题这两行在不同tikv中一行成功一行事务。begin - 获取tso - 然后发出commit; 然后进入两阶段prewrite: 数据写入到tikv 锁写入tikv整个分布事务中只在第一行加锁或者说主锁也就是pk。1,(W,pk,1,100 …) 第一行上加主锁2,(W,1,2,100 …) 第二行 1我不是主锁锁在1上这是一个指向。 其他行都是加的指向写入到tikv的时候只需要记录修改后的1,Jack新值即可不需要记录1,Tom的内容。此时读 id 2 的时候它会查看有没有锁看到有把锁虽然不是主锁但它对应指向的主锁上主锁状态时W说明它此时也正在事务中不能读。commit: 获取tso write信息 清理锁信息先从pd中获取时间戳然后写入提交信息。 先在相应的tikv上写1_事务提交时间,事务开始时间然后清理锁信息。 清理机制主锁信息上面加一行D. 非主锁上面也是加一行。读取的时候 加入现在时间是120首先到write cf中 找到最晚一次提交找到1_110,100,然后找到100-110之间的default。如果原子性破坏这种机制能否防止。tikv 1 成功 id1的持久化了tikv 2 失败 id2的没有持久化down掉了这个时候怎么办当读取node2 的write cf 的CF的时候 没有读取到内容这个时候接着去Lock中读到了一把锁 2 (w,1,2,100)但这个不是主锁它是指向id1. 这个时候找id1上锁的信息发现id1的主锁被删掉了这个时候可能就知道在被修改的时候 中间出现了状况例如down机。然后这个时候会进行判断发现tikv 1上已经提交。这个会将相关信息补上。不上之后再读取就可以了。整个分布式事务的解决这么多行的修改 实际上落脚点就在 第一行的主锁事务成功或者不成功就看主锁其他都是指向。 如果其他节点出现了down机没关系起来了之后看指向主锁的信息看它有没有成功如果成功了。 没有做的提交信息和索引信息补上就可以了。mvcc某行正在事务中无论读和写都会返回锁信息表示不能读和写。如果修改的事务中有10w的数据在做修改的时候 则这些都不能读和写业务马上串行这肯定不行。 所以这个时候就有MVCCid 1 假设当前tso 是120读取操作首先读write CF ,还有个指针指向Lock CF在write CF中id1 最近一次已提交的记录 1_110,100 则拿着1_100到default中找找。写操作首先读write CF ,还有个指针指向Lock CF在write CF中id1 最近一次已提交的记录 1_110,100 但可以看到Lock中有条目 1,(W,pk,1,115…)的时候已经被修改了。这个时候写入会被阻塞所以这个就是写不阻塞读id2 假设当前tso 是120读取操作首先读write CF ,还有个指针指向Lock CF在write CF中id2 最近一次已提交的记录 2_110,100 则拿着2_100到default中找找。 candy写操作首先读write CF ,还有个指针指向Lock CF在write CF中id2 最近一次已提交的记录 2_110,100 并且Lock中并没有id2 锁的信息。这个时候其他写入正常执行。所以读写都可以id4 假设当前tso 是120读取操作由于id4 所在的事务未提交所以要找最近的一次的提交事务是 4_90,80 。 90的时候提交过一次所已找4_80. 找到tony写操作由于id4 所在的事务未提交所以要找最近的一次的提交事务是 4_90,80。除了这个还需要到Lock CF中查找。 一看找到写锁然后要判断这个写锁状态找到对应主锁。找到 1(w,pk,1,115)说明4正在事务中表明写操作被阻塞。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2408524.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!