原文链接:
http://click.aliyun.com/m/26466/
摘要: --- title: MySQL · myrocks · myrocks写入分析 author: 张远 --- # 写入流程 myrocks的写入流程可以简单的分为以下几步来完成 1. 将解析后的记录(kTypeValue/kTypeDeletion)写入到WriteBatch中 2. 将WAL日志写入log文件 3. 将WriteBatch中的内容写到memtabl
title: MySQL · myrocks · myrocks写入分析
author: 张远
写入流程
myrocks的写入流程可以简单的分为以下几步来完成
将解析后的记录(kTypeValue/kTypeDeletion)写入到WriteBatch中
将WAL日志写入log文件
将WriteBatch中的内容写到memtable中,事务完成
其中第2,3步在提交时完成
WriteBatch与Myrocks事务处理密切相关,事务中的记录提交前都以字符串的形式存储在WriteBatch->rep_中,要么都提交,要么都回滚。 回滚的逻辑比较简单,只需要清理WriteBatch->rep_即可。详见TransactionImpl::Rollback
一个简单的insert 写入WriteBatch堆栈如下
#0 rocksdb::WriteBatchInternal::Put
#1 rocksdb::WriteBatch::Put
#2 myrocks::ha_rocksdb::update_pk
#3 myrocks::ha_rocksdb::update_indexes
#4 myrocks::ha_rocksdb::update_write_row
#5 myrocks::ha_rocksdb::write_row
#6 handler::ha_write_row
#7 write_record
#8 mysql_insert
#9 mysql_execute_command
#10 mysql_parse
#11 dispatch_command
#12 do_command
#13 do_handle_one_connection
一个简单的insert commit堆栈如下
#0 rocksdb::InlineSkipList<rocksdb::MemTableRep::KeyComparator const&>::Insert
#1 rocksdb::(anonymous namespace)::SkipListRep::Insert
#2 rocksdb::MemTable::Add
#3 rocksdb::MemTableInserter::PutCF
#4 rocksdb::WriteBatch::Iterate
#5 rocksdb::WriteBatch::Iterate
#6 rocksdb::WriteBatchInternal::InsertInto
#7 rocksdb::DBImpl::WriteImpl
#8 rocksdb::DBImpl::Write
#9 rocksdb::TransactionImpl::Commit
#10 myrocks::Rdb_transaction_impl::commit_no_binlog
#11 myrocks::Rdb_transaction::commit
#12 myrocks::rocksdb_commit
#13 ha_commit_low
#14 TC_LOG_MMAP::commit
#15 ha_commit_trans
#16 trans_commit_stmt
#17 mysql_execute_command
#18 mysql_parse
#19 dispatch_command
#20 do_command
#21 do_handle_one_connection
提交流程及优化
这里只分析rocksdb引擎的提交流程,实际MyRocks提交时还需先写binlog(binlog开启的情况).
rocksdb引擎提交时就完成两个事情
1. 写WAL日志(WAL开启的情况下rocksdb_write_disable_wal=off)
2. 将之前的WriteBatch写入到memtable中
然而,写WAL是一个串行操作。为了提高提交的效率, rocksdb引入了group commit机制。
待提交的事务都依次加入到提交的writer队列中,这个writer队列被划分为一个一个group. 每个group有一个leader, 其他为follower,leader负责批量写WAL。每个group由双向链表link_older, link_newer链接。如下图所示
屏幕快照 2017-07-11 下午7.46.22.png
每个writer可能的状态如下
Init: writer的初始状态
Header: writer被选为leader
Follower: writer被选为follower
LockedWating: writer在等待自己转变为指定的状态
Completed:writer操作完成
writer的状态变迁跟group是否并发写memtable有关
当开启并发写memtable(rocksdb_allow_concurrent_memtable_write=on)且group中的writer至少有两个时,group才会并发写。
group并发写时writer的状态变迁图如下:
屏幕快照 2017-07-14 下午1.25.27.png
group非并发写时writer的状态变迁图如下:
屏幕快照 2017-07-11 下午7.46.50.png
源码结构图如下(图片来自林青)
屏幕快照 2017-07-14 下午1.44.46.png
上面的图是在group内writer并发写memtable的情形。
非并发写memtable时,没有LaunchParallelFollowers/CompleteParallelWorker, Insertmemtable是由leader串行写入的。
这里group commit有以下要点
1. 同一时刻只有一个leader, leader完成操作后,才设置下一个leader
2. 需要等一个group都完成后,才会进行下一个group
3. group中最后一个完成的writer负责完成提交和设置下一个leader
4. Leader 负责批量写WAL
5. 只有leader才会去调整双向链表link_older,link_newer.
注意这里2,3 应该可以优化改进为
不需要等一个group完成再进行下一个group
不同group的follower可以并发执行
只有leader负责完成提交和设置下一个leader
写入控制
rocksdb在提交写入时,需考虑以下几种情况,详见PreprocessWrite
WAL日志满,WAL日志超过rocksdb_max_total_wal_size,会从所有的colomn family中找出含有最老日志(the earliest log containing a prepared section)的column family进行flush, 以释放WAL日志空间
Buffer满,全局的write buffer超过rocksdb_db_write_buffer_size时,会从所有的colomn family中找出最先创建的memtable进行切换,详见HandleWriteBufferFull
某些条件会触发延迟写
max_write_buffer_number > 3且 未刷immutable memtable总数 >=max_write_buffer_number-1
自动compact开启时,level0的文件总数 >= level0_slowdown_writes_trigger
某些条件会触发停写
未刷immutable memtable总数 >=max_write_buffer_number
自动compact开启时,level0的文件总数 >= level0_stop_writes_trigger
具体可参考RecalculateWriteStallConditions
总结
rocksdb写入流程还有优化空间,Facebook也有相关的优化。
如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
原文链接:
http://click.aliyun.com/m/26466/
分享到:
相关推荐
1. WriteBatch:MyRocks 使用 WriteBatch 来批量写入数据,以提高写入性能。 2. Every Trx has WriteBatch:每个事务都有一个对应的 WriteBatch,以确保事务的一致性。 3. DML buffered in WriteBatch:MyRocks 将 ...
4. **更小的写入放大**:由于MyRocks的LSM-Tree结构,写入放大相对于InnoDB更低,对SSD的寿命更有利。 **应用案例**: 在大数据量业务中,MyRocks的优势明显。例如,某业务面临写多读少、存储成本高、增长速度快等...
“写入测量文件”Express VI位于函数选板的“编程→文件I/O→写入测量文件”,完整的图标和接线端如图1所示。 写入测量文件Express VI将数据写入基于文本或二进制的测量文件。输入和输出接线端说明如下。 ...
这种操作在实际应用中非常常见,如数据分析、数据挖掘、科学计算等领域。在Java中,写入大数据文件通常需要考虑文件的大小、写入速度、内存占用等因素,以确保写入操作的高效性和可靠性。 在给定的Java代码中,我们...
本工具专注于串口的读取和写入功能,并支持将数据写入文件,这对于数据记录、分析或调试非常有用。 串口通信的基本原理是通过串行数据线(通常为RX和TX)传输数据,以比特(bit)为单位,逐位发送。与并行通信相比...
**原理分析:** 1. **块擦除特性**:在SSD中,数据只能在空闲的块中写入,并且一旦写入就不能直接覆盖修改,而必须先擦除整个块才能重新写入新数据。 2. **垃圾回收机制**:为了保持一定的空闲空间,SSD会定期执行...
“写入电子表格文件”位于函数选板的“编程→文件I/O→写入电子表格文件”,图标和接线端如图1所示。 图1 写入电子表格文件图标和接线端 输入和输出接线端说明如下。 format(%3f):格式(%3f),...
在LabVIEW中,我们可以通过编程实现对CSV文件的创建和写入,以便于后续的数据分析和处理。 首先,我们需要了解LabVIEW中的文件I/O(输入/输出)函数。在LabVIEW的函数选板中,通常可以在“字符串”类别下找到与文件...
"黑苹果CDR格式镜像文件写入软件"是指用于在Windows系统中将特定的CDR格式镜像文件写入到硬盘或者可移动存储设备上的工具。这种软件主要用于安装或配置"黑苹果"(Black Apple),即在非苹果硬件上运行苹果的操作系统...
在C++编程中,创建、打开并写入记事本文件是一种常见的操作,尤其是在学习文件I/O时。这里我们将详细探讨如何使用C++实现这个功能,并通过`system()`函数调用操作系统命令来显示记事本,查看写入的数据。首先,我们...
这些技术广泛应用于自动化测试报告生成、数据分析报告、批量修改模板文档等场景。通过结合LabVIEW的数据处理能力和Word的富文本编辑功能,可以构建强大的文档处理解决方案。 在学习和使用这些VI时,建议深入理解每...
"Ubuntu Linux镜像U盘写入工具"正是为了解决这一需求而设计的,它能够帮助用户将Ubuntu的ISO镜像文件高效且无误地写入到U盘中,以便于制作可启动的Ubuntu安装盘。 Ubuntu安装光盘镜像文件是Ubuntu发行版的完整复制...
标题中的“win U盘镜像写入工具 win32diskiamger”指的是Windows操作系统下用于将ISO镜像文件写入到U盘的实用工具——Win32 Disk Imager。这个工具广泛应用于创建可启动U盘,例如制作安装系统或者修复工具的USB驱动...
通过上述分析,我们可以看到Java读取和写入CSV文件的过程涉及到多个步骤,包括初始化读写器、循环读取或写入数据、异常处理以及资源释放。正确地理解和应用这些步骤对于高效处理CSV文件至关重要。 此外,使用日志...
在这个环境中,“对每一个单元格写入输入”指的是在LabVIEW的数据结构,如数组或矩阵中,逐个指定位置进行数据写入的操作。这种操作在处理多列列表时非常常见,例如在数据分析、实验数据记录或者界面交互应用中。 1...
C# 使用 StreamWriter 写入数据 C# 使用 StreamWriter 写入数据 C# 使用 StreamWriter 写入数据 C# 使用 StreamWriter 写入数据 C# 使用 StreamWriter 写入数据 C# 使用 StreamWriter 写入数据
STM32F103系列微控制器是基于ARM Cortex-M3内核...通过分析和调试代码,可以深入理解SD卡文件系统的运作原理和STM32的SDIO接口操作。同时,这也是一个良好的学习资源,帮助初学者快速掌握嵌入式系统中的文件操作技术。
Java实现批量向mysql写入数据的方法 Java语言是目前最流行的编程语言之一,在数据库应用中,Java语言广泛应用于与数据库的交互,特别是mysql数据库。mysql数据库是目前最流行的开源关系数据库管理系统,它提供了...
【MTK串号写入工具】是一款专门针对搭载联发科(MediaTek)CPU的智能手机设计的软件工具,主要用于IMEI(国际移动设备识别码)的写入和恢复操作。IMEI是每部手机独一无二的识别码,由15位数字组成,用于在全球范围内...
“写入二进制文件”位于函数选板的“编程→文件I/O一写入二进制文件”,图标和接线端如图1所示。 输入和输出接线端的说明如下。 prepend arrav Or string slze?:预置数组或字符串大小,指定是否包含写入...