所谓活跃事务就是处于执行中的事务,对于RC以上隔离界别,活跃事务都是不可见的 。前面提到过,SERIALIZABLE是通过行级锁实现的,不必考虑可见性 。
一般来说,RC可见性是语句级别的,RR可见性是事务级别的 。这在TokuDB中是如何实现的呢?
每个语句执行开始都会创建一个子事务 。如果是RC、RR隔离级别,还会创建snapshot 。Snapshot也有活跃事务列表,RC隔离级别是复制事务mgr在语句事务开始时刻的活跃事务列表,RR隔离级别是复制事务mgr在server层事务开始时刻的活跃事务列表 。
Snapshot可见性就是事务id比snapshot的事务id更小,意味着更早开始执行;但是不在snapshot活跃事务列表的事务 。
GC
随着事务提交snapshot结束,老版本数据不在被访问需要清理,这就引入了GC的问题 。
为了判断写事务的更新是否被其他事务访问,TokuDB的事务mgr维护了referencexids数组,记录事务提交时刻,系统中处于活跃状态snapshot个数,作用相当于referencecount 。
以上描述了TokuDB如何跟踪写事务的引用者 。那么GC是何时执行的呢?
可以调用OPTIMIZE TABLE显式触发,也可以在后续访问索引key时隐式触发 。
典型业务场景
以上介绍了TokuDB引擎内核原理,下面我们从HybridDB for MySQL产品的角度谈一下业务场景和性能 。
HybridDB for MySQL设计目标是提供低成本大容量分布式数据库服务,一体式处理OLTP和OLAP混合业务场景,提供存储和计算能力;而存储和计算节点在物理上是分离的,用户可以根据业务特点定制存储计算节点的配比,也可以单独购买存储和计算节点 。
HybridDB for MySQL数据只存储一份,减少数据交换成本,同时也降低了存储成本;所有功能集成在一个实例之中,提供统一的用户接口,一致的数据视图和全局统一的SQL兼容性 。
HybridDB for MySQL支持数据库分区,整体容量和性能随分区数目增长而线性增长;用户可先购买一个基本配置,随业务发展后续可以购买更多的节点进行扩容 。HybridDB for MySQL提供在线的扩容和缩容能力,水平扩展/收缩存储和计算节点拓扑结构;在扩展过程中,不影响业务对外提供服务,优化数据分布算法,减少重新分布数据量;采用流式迁移,备份数据不落地 。
除此之外,HybridDB for MySQL还支持高可用,复用链路高可用技术,采用一主多备方式实现三副本 。HybridDB for MySQL复用ApsaraDB for MySQL已有技术框架,部署、升级、链路管理、资源管理、备份、安全、监控和日志复用已有功能模块,技术风险低,验证周期短,可以说是站在巨人肩膀上的创新 。
文章插图
低成本大容量存储场景
HybridDB for MySQL使用软硬件整体方案解决大容量低成本问题 。
软件方面,HybridDB for MySQL是分布式数据库,摆脱单机硬件资源限制,提供横向扩展能力,容量和性能随节点数目增加而线性增加 。存储节点MySQL实例选择使用TokuDB引擎,支持块级压缩,压缩算法以表单位进行配置 。用户可根据业务自身特点选择使用压缩效果好的压缩算法比如lzma,也可以选择quicklz这种压缩速度快资源消耗低的压缩算法,也可以选择像zstd这种压缩效果和压缩速度比较均衡的压缩算法 。如果选用zstd压缩算法,线上实测的压缩比是3~4 。
硬件方面,HybridDB for MySQL采用分层存储解决方案,大量冷数据存储在SATA盘上,少量温数据存储在ssd上,热数据存储在数据库引擎的内存缓存中(TokuDB cachetable) 。SATA盘和ssd上数据之间的映射关系通过bcache驱动模块来管理,bcache可以配置成WriteBack模式(写路径数据写ssd后即返回,ssd中更新数据由bcache负责同步到SATA盘上),可加速数据库checkpoint写盘速度;也可以配置成WriteThrough模式(写路径数据同时写到ssd和SATA上,两者都ack写才算完成) 。
持续高并发写入场景
TokuDB采用fractal tree(中文译作分型树)数据结构,优化写路径,大部分二级索引的写操作是异步的,写被缓存到中间数据块即返回 。写操作同步到叶数据块可以通过后台cleaner线程异步完成,也可能由后续的读操作同步完成(读合并) 。Fractal tree在前面的内核原理部分有详尽描述,这里就不赘述了 。
细心的朋友可能会发现,我们在异步写前加了个前缀:大部分二级索引 。那么大部分是指那些情况呢?这里大部分是指不需要做quickness检查的索引,写请求直接扔给fractal tree的msg buffer即可返回 。如果二级索引包含unique索引,必须先做唯一性检查保证不存在重复键值 。否则,异步合并(或者读合并)无法通知唯一性检查失败,也无法回滚其他索引的更新 。Pk字段也有类似的唯一性语义,写之前会去查询pk键值是否已存在,顺便做了root到leaf数据块的预读和读合并 。所以,每条新增数据执行INSERT INTO的过程不完全是异步写 。
推荐阅读
- 梦见几棵大树又高又粗 梦见一颗很高的大树倒了
- 如何挑选娃娃菜
- 清明上坟时间有什么讲究 清明上坟从高祖开始拜还是辈份低开始
- 全球公认最好用的10大眼霜 十大高端眼霜
- 深圳的平安大厦高多少米 深圳最高楼是平安大厦吗
- 高考将近家长要稳字当头 高三家长会发言稿
- 营造拥有你独特气息的高雅茶席
- 汽车发动机水温高报警怎么办?值得收藏备用!
- 事业单位改革后,高校教师、医生、参公人员哪个更有发展?
- 发动机水温高的原因是?