源码分析 | ClickHouse和他的朋友们(2)MySQL Protocol和Read调用栈

MySQL协议解析MysqlProtocolAnalyzer.zip MysqlProtocolAnalyzer 是一个对Mysql的通讯协议的包进行解析的库,纯java编写,输入文件可以是任意的16进制的文本文件,当然需要一定的预处理才能使用。本库是默认处理的是tcpdump产生的16进制的数据文件 能解析客户端与mysql服务交互的所有包,例如客户端与服务器连接的握手协议的包,所有COM_QUERY类型的语句,COM_STMT_PREPARE和COM_STMT_EXECUTE,还有ok包,以及resultset包等。 立即下载

本文首发于 2020-06-07 17:17:10

《ClickHouse和他的朋友们》系列文章转载自圈内好友 BohuTANG 的博客,原文链接:
https://bohutang.me/2020/06/07/clickhouse-and-friends-mysql-protocol-read-stack/
以下为正文。

作为一个 OLAP 的 DBMS 来说,有2个端非常重要:

  • 用户如何方便的链进来,这是入口端
    • ClickHouse 除了自己的 client 外,还提供了 MySQL/PG/GRPC/HTTP 等接入方式
  • 数据如何方便的挂上去,这是数据源端
    • ClickHouse 除了自己的引擎外,还可以挂载 MySQL/Kafka 等外部数据源

这样内外互通,多条朋友多条路,以实现“数据”级的编排能力。

今天谈的是入口端的 MySQL 协议,也是本系列 ClickHouse 的第一个好朋友,用户可通过 MySQL 客户端或相关 Driver 直接链接到 ClickHouse,进行数据读写等操作。

本文通过 MySQL的 Query 请求,借用调用栈来了解下 ClickHouse 的数据读取全过程。

如何实现?

入口文件在:
MySQLHandler.cpp

握手协议

  1. MySQLClient 发送 Greeting 数据报文到 MySQLHandler
  2. MySQLHandler 回复一个 Greeting-Response 报文
  3. MySQLClient 发送认证报文
  4. MySQLHandler 对认证报文进行鉴权,并返回鉴权结果

MySQL Protocol 实现在: Core/MySQLProtocol.h

最近的代码中调整为了 Core/MySQL/PacketsProtocolText.h

Query请求

当认证通过后,就可以进行正常的数据交互了。

  1. 当 MySQLClient 发送请求:

    mysql> SELECT * FROM system.numbers LIMIT 5;
    
  2. MySQLHandler 的调用栈:

    ->MySQLHandler::comQuery -> executeQuery -> pipeline->execute -> MySQLOutputFormat::consume
    
  3. MySQLClient 接收到结果

在步骤2里,executeQuery(executeQuery.cpp)非常重要。
它是所有前端 Server 和 ClickHouse 内核的接入口,第一个参数是 SQL 文本(‘select 1’),第二个参数是结果集要发送到哪里去(socket net)。

调用栈分析

SELECT * FROM system.numbers LIMIT 5

1. 获取数据源

StorageSystemNumbers 数据源:

DB::StorageSystemNumbers::read(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, std::__1::shared_ptr<DB::StorageInMemoryMetadata const> const&, DB::SelectQueryInfo const&, DB::Context const&, DB::QueryProcessingStage::Enum, unsigned long, unsigned int) StorageSystemNumbers.cpp:135
DB::ReadFromStorageStep::ReadFromStorageStep(std::__1::shared_ptr<DB::RWLockImpl::LockHolderImpl>, std::__1::shared_ptr<DB::StorageInMemoryMetadata const>&, DB::SelectQueryOptions,
DB::InterpreterSelectQuery::executeFetchColumns(DB::QueryProcessingStage::Enum, DB::QueryPlan&, std::__1::shared_ptr<DB::PrewhereInfo> const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) memory:3028
DB::InterpreterSelectQuery::executeFetchColumns(DB::QueryProcessingStage::Enum, DB::QueryPlan&, std::__1::shared_ptr<DB::PrewhereInfo> const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) InterpreterSelectQuery.cpp:1361
DB::InterpreterSelectQuery::executeImpl(DB::QueryPlan&, std::__1::shared_ptr<DB::IBlockInputStream> const&, std::__1::optional<DB::Pipe>) InterpreterSelectQuery.cpp:791
DB::InterpreterSelectQuery::buildQueryPlan(DB::QueryPlan&) InterpreterSelectQuery.cpp:472
DB::InterpreterSelectWithUnionQuery::buildQueryPlan(DB::QueryPlan&) InterpreterSelectWithUnionQuery.cpp:183
DB::InterpreterSelectWithUnionQuery::execute() InterpreterSelectWithUnionQuery.cpp:198
DB::executeQueryImpl(const char *, const char *, DB::Context &, bool, DB::QueryProcessingStage::Enum, bool, DB::ReadBuffer *) executeQuery.cpp:385
DB::executeQuery(DB::ReadBuffer&, DB::WriteBuffer&, bool, DB::Context&, std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&,
DB::MySQLHandler::comQuery(DB::ReadBuffer&) MySQLHandler.cpp:307
DB::MySQLHandler::run() MySQLHandler.cpp:141

这里最主要的是 ReadFromStorageStep 函数,从不同 storage 里获取数据源 pipe:

Pipes pipes = storage->read(required_columns, metadata_snapshot, query_info, *context, processing_stage, max_block_size, max_streams);

2. Pipeline构造

DB::LimitTransform::LimitTransform(DB::Block const&, unsigned long, unsigned long, unsigned long, bool, bool, std::__1::vector<DB::SortColumnDescription, std::__1::allocator<DB::SortColumnDescription> >) LimitTransform.cpp:21
DB::LimitStep::transformPipeline(DB::QueryPipeline&) memory:2214
DB::LimitStep::transformPipeline(DB::QueryPipeline&) memory:2299
DB::LimitStep::transformPipeline(DB::QueryPipeline&) memory:3570
DB::LimitStep::transformPipeline(DB::QueryPipeline&) memory:4400
DB::LimitStep::transformPipeline(DB::QueryPipeline&) LimitStep.cpp:33
DB::ITransformingStep::updatePipeline(std::__1::vector<std::__1::unique_ptr<DB::QueryPipeline, std::__1::default_delete<DB::QueryPipeline> >, std::__1::allocator<std::__1::unique_ptr<DB::QueryPipeline, std::__1::default_delete<DB::QueryPipeline> > > >) ITransformingStep.cpp:21
DB::QueryPlan::buildQueryPipeline() QueryPlan.cpp:154
DB::InterpreterSelectWithUnionQuery::execute() InterpreterSelectWithUnionQuery.cpp:200
DB::executeQueryImpl(const char *, const char *, DB::Context &, bool, DB::QueryProcessingStage::Enum, bool, DB::ReadBuffer *) executeQuery.cpp:385
DB::executeQuery(DB::ReadBuffer&, DB::WriteBuffer&, bool, DB::Context&, std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)>) executeQuery.cpp:722
DB::MySQLHandler::comQuery(DB::ReadBuffer&) MySQLHandler.cpp:307
DB::MySQLHandler::run() MySQLHandler.cpp:141

3. Pipeline执行

DB::LimitTransform::prepare(std::__1::vector<unsigned long, std::__1::allocator<unsigned long> > const&, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> > const&) LimitTransform.cpp:67
DB::PipelineExecutor::prepareProcessor(unsigned long, unsigned long, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, std::__1::unique_lock<std::__1::mutex>) PipelineExecutor.cpp:291
DB::PipelineExecutor::tryAddProcessorToStackIfUpdated(DB::PipelineExecutor::Edge&, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, unsigned long) PipelineExecutor.cpp:264
DB::PipelineExecutor::prepareProcessor(unsigned long, unsigned long, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, std::__1::unique_lock<std::__1::mutex>) PipelineExecutor.cpp:373
DB::PipelineExecutor::tryAddProcessorToStackIfUpdated(DB::PipelineExecutor::Edge&, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, unsigned long) PipelineExecutor.cpp:264
DB::PipelineExecutor::prepareProcessor(unsigned long, unsigned long, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, std::__1::unique_lock<std::__1::mutex>) PipelineExecutor.cpp:373
DB::PipelineExecutor::tryAddProcessorToStackIfUpdated(DB::PipelineExecutor::Edge&, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, unsigned long) PipelineExecutor.cpp:264
DB::PipelineExecutor::prepareProcessor(unsigned long, unsigned long, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, std::__1::unique_lock<std::__1::mutex>) PipelineExecutor.cpp:373
DB::PipelineExecutor::tryAddProcessorToStackIfUpdated(DB::PipelineExecutor::Edge&, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, unsigned long) PipelineExecutor.cpp:264
DB::PipelineExecutor::prepareProcessor(unsigned long, unsigned long, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, std::__1::unique_lock<std::__1::mutex>) PipelineExecutor.cpp:373
DB::PipelineExecutor::tryAddProcessorToStackIfUpdated(DB::PipelineExecutor::Edge&, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, unsigned long) PipelineExecutor.cpp:264
DB::PipelineExecutor::prepareProcessor(unsigned long, unsigned long, std::__1::queue<DB::PipelineExecutor::ExecutionState*, std::__1::deque<DB::PipelineExecutor::ExecutionState*, std::__1::allocator<DB::PipelineExecutor::ExecutionState*> > >&, std::__1::unique_lock<std::__1::mutex>) PipelineExecutor.cpp:373
DB::PipelineExecutor::initializeExecution(unsigned long) PipelineExecutor.cpp:747
DB::PipelineExecutor::executeImpl(unsigned long) PipelineExecutor.cpp:764
DB::PipelineExecutor::execute(unsigned long) PipelineExecutor.cpp:479
DB::executeQuery(DB::ReadBuffer&, DB::WriteBuffer&, bool, DB::Context&, std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)>) executeQuery.cpp:833
DB::MySQLHandler::comQuery(DB::ReadBuffer&) MySQLHandler.cpp:307
DB::MySQLHandler::run() MySQLHandler.cpp:141

4. Output执行发送

DB::MySQLOutputFormat::consume(DB::Chunk) MySQLOutputFormat.cpp:53
DB::IOutputFormat::work() IOutputFormat.cpp:62
DB::executeJob(DB::IProcessor *) PipelineExecutor.cpp:155
operator() PipelineExecutor.cpp:172
DB::PipelineExecutor::executeStepImpl(unsigned long, unsigned long, std::__1::atomic<bool>*) PipelineExecutor.cpp:630
DB::PipelineExecutor::executeSingleThread(unsigned long, unsigned long) PipelineExecutor.cpp:546
DB::PipelineExecutor::executeImpl(unsigned long) PipelineExecutor.cpp:812
DB::PipelineExecutor::execute(unsigned long) PipelineExecutor.cpp:479
DB::executeQuery(DB::ReadBuffer&, DB::WriteBuffer&, bool, DB::Context&, std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)>) executeQuery.cpp:800
DB::MySQLHandler::comQuery(DB::ReadBuffer&) MySQLHandler.cpp:311
DB::MySQLHandler::run() MySQLHandler.cpp:141

总结

ClickHouse 的模块化比较清晰,像乐高积木一样可以组合拼装,当我们执行:

SELECT * FROM system.numbers LIMIT 5

首先内核解析 SQL 语句生成 AST,然后根据 AST 获取数据源 Source,pipeline.Add(Source)。
其次根据 AST 信息生成 QueryPlan,根据 QueryPlan 再生成相应的 Transform,pipeline.Add(LimitTransform)。
然后添加 Output Sink 作为数据发送对象,pipeline.Add(OutputSink)。
执行 pipeline, 各个 Transformer 开始工作。

ClickHouse 的 Transformer 调度系统叫做 Processor,也是决定性能的重要模块,详情见 Pipeline 处理器和调度器。
ClickHouse 是一辆手动挡的豪华跑车,免费拥有,海啸们!


欢迎关注我的微信公众号【数据库内核】:分享主流开源数据库和存储引擎相关技术。

标题网址
GitHubhttps://dbkernel.github.io
知乎https://www.zhihu.com/people/…
思否(SegmentFault)https://segmentfault.com/u/db…
掘金https://juejin.im/user/5e9d3e…
开源中国(oschina)https://my.oschina.net/dbkernel
博客园(cnblogs)https://www.cnblogs.com/dbkernel
SIMULINK开发项目实例 1000 例专栏之第912例--AC-DC整流器场景:基于PWM整流器拓扑结构的建模:三相电压型PWM整流器(SR)单位功率因数控制仿真 本文详细介绍了使用Simulink和Simscape Electrical搭建三相电压型PWM整流器(VSR)模型的方法。主要内容包括:系统结构设计、主电路拓扑搭建、单位功率因数控制算法实现(含PLL锁相环、dq变换、PI控制器等模块)、参数配置和仿真设置。通过仿真分析验证了该系统能实现输入电流与电压同相位、输出直流电压稳定等特性,体现了PWM整流器的高效性和低谐波优势。文章还提出了增强鲁棒性、多工况测试等优化建议,为电力电子系统设计提供了实用指导。该建模方法对新能源发电、电动汽车充电等领域具有重要意义。 阅读详情

相关推荐

别再为10G UDP发愁了!手把手教你用Xilinx 10G/25G Ethernet Subsystem IP核搭建FPGA网络栈(附12套工程源码)

本文详细介绍了基于Xilinx UltraScale架构的FPGA网络栈开发,重点讲解了10G/25G Ethernet Subsystem IP核的应用实践。通过手把手教程和12套工程源码,帮助开发者解决10G UDP通信中的物理层接口、协议栈实现和系统集成等核心挑战,实现高性能FPGA网络栈搭建。

weixin_42522575的博客 365

MysqlProtocolAnalyzer:深入解析MySQL协议的强大工具

MysqlProtocolAnalyzer:深入解析MySQL协议的强大工具 在数据库开发和管理中,理解SQL语句如何转化为网络协议进行传输是至关重要的。是一个开源项目,旨在帮助开发者和DBA直观地解析和分析MySQL通信协议,从而提升性能优化和故障排查的能力。 项目简介 MysqlProtocolAnalyzer是一款基于Python编写的轻量级工具,它可以解码并显示MySQL客户端与服务器之间...

gitblog_00027的博客 697

一张图看懂中国民航适航审定体系:从适航司到审定中心,到底谁管谁?

本文深入解析中国民航适航审定体系,从立法层到执行层的完整链条,揭示适航管理的金字塔结构和核心流程。涵盖适航司、审定中心等关键机构职能,以及型号审定、生产许可审定等全生命周期管理,展现中国适航体系的特色实践与创新探索。

weixin_30896511的博客 477

MySQL 协议(非常详细适合小白学习)

MySQL 查询过程大致如下:1)客户端与服务器端建立连接;2)客户端登陆 MySQL;3)客户端向服务器端发起一条请求;4)服务器端先检查查询缓存,如果命中缓存,则直接返回结果;否则交给下一阶段;5)服务器进行 SQL 解析并生成解析树及执行计划(初始执行计划);6)服务器对解析树进行查询优化(RBO、CBO)并生成最终执行计划;7)MySQL 根据执行计划,调用相应 API,以进行数据的读取;8)将从存储引擎读取的结果返回给客户端,并缓存查询结果。

热爱数据库的小胖 4366

SPL06气压温度传感器SPI驱动与补偿算法详解

气压传感器与温度传感器是嵌入式环境感知系统的核心组件,其测量精度高度依赖于MEMS芯片的校准参数与非线性补偿机制。SPL06作为集成式高精度数字传感器,采用24位Σ-Δ ADC与片内补偿引擎,需结合唯一出厂校准系数(即‘芯片指纹’)进行多阶数学修正,才能将原始ADC值转化为符合计量要求的帕斯卡(Pa)与摄氏度(℃)物理量。该过程涵盖SPI通信协议解析、寄存器时序控制、大端数据拼接、二进制补码处理及浮点/定点混合运算等典型嵌入式工程实践。广泛应用于无人机高度计、智能穿戴海拔监测与IoT气象终端中。

weixin_34640289的博客 143

LangChain开发避坑指南:为什么Pylance总提示‘无法解析导入‘?实测7种修复方案

本文深入解析了在VS Code中使用LangChain开发时,Pylance频繁提示‘无法解析导入’的根本原因——Python解释器与语言服务器的环境路径不一致。文章提供了从基础排查到深度配置的7种实测修复方案,包括切换解释器、配置extraPaths、使用pyrightconfig.json等,旨在帮助开发者彻底解决此问题,提升AI应用开发效率。

weixin_28826521的博客 447

mysql protocol_Mysql protocol

走了那么长的弯路,真有点杯具啊。哎,算了,好好来说说mysql protocol吧。一、Packet类型:1.The Handshake (when client connects):Server Sends To Client: Handshake Initialisation PacketClient Sends To Server: Client Authentication PacketS...

weixin_42386819的博客 373

【从零开始学习 SystemVerilog】1.1、SystemVerilog 概述

【从零开始学习 SystemVerilog】1.1、SystemVerilog 概述

努力,加油每一天鸭~ 1038

mysql协议详解

MySQL协议是MySQL客户端与服务器之间通信的核心规则,定义了数据交换的格式、流程及指令。低版本客户端连接高版本服务器时,可能因认证插件不兼容导致失败(如MySQL 5.7客户端连接MySQL 8.0)。caching_sha2_password:MySQL 8.0+默认,使用SHA256算法。Wireshark:直接解析MySQL协议,查看握手、查询、响应等流程。包长度(3字节):Payload部分的字节数(0~16MB)。Payload(变长):实际传输的数据(指令、结果、错误等)。

技术人集结地 1870

第4篇:使用 NModbus 库快速搭建 Modbus TCP 通信(从零开始用 C# 开发 Modbus 上位机)

本文介绍了如何使用 NModbus 库快速搭建 Modbus TCP 上位机通信程序。通过安装 NModbus4 NuGet 包,开发者可以轻松实现 Modbus TCP 连接,无需手动处理底层协议细节。文章详细演示了核心功能实现: 创建 TCP 客户端连接设备 读取保持寄存器(功能码0x03) 写入单个寄存器(功能码0x06) 关闭连接释放资源 提供完整C#示例代码,包含初始化连接、数据读写等关键操作,帮助开发者快速构建Modbus TCP通信应用。相比手动实现,NModbus库大幅简化了开发流程,特别适

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1047

tsfknn 预测R语言中的时间序列

rolling参数应该设置为FALSE,这使得最后的18个观测值成为测试集,其余的作为训练集;如果我们将rolling参数设置为默认值TRUE,那么测试集就不会是一个恒定的向量。lag 滞后参数表示时间序列数据的滞后值。在这个例子中,由于我们的时间序列数据是月度的,我们将参数设置为1:12。作为药品福利计划的一部分,澳大利亚健康保险委员会记录的属于ATC代码A10的产品的每月政府支出(百万美元)。我们将使用tsfknn包,它可以用来预测R语言中的时间序列。格式:ts类别的月度时间序列。

Mrrunsen的博客 325

MySQL Internals ClientServer Protocol

转载自:http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol MySQL Internals ClientServer Protocol [edit] MySQL Client/Server Protocol [edit] Organization The topic is: the ...

云计算? 584

YOLO项目从零开始:超详细运行教程(图文保姆级教学)

至此,我们已经完整跑通了YOLO项目的安装与启动流程,无论你是零基础小白还是刚入门的AI新兵,只要按部就班操作,也能轻松实现目标检测项目的落地。

一键难忘的博客 4803

源码分析 | ClickHouse和他的朋友们(3)MySQL Protocol和Write调用栈

本文首发于 2020-06-08 19:57:10上篇的MySQL Protocol和Read调用里介绍了 ClickHouse 一条查询语句的调用栈,本文继续介绍写的调用栈,开整。建表: 写入数据: 调用栈分析 1. 获取存储引擎 OutputStream 2. 从 SQL 组装 InputStream 如何组装成 inputstream 结构呢? 然后 通过 NullAndDoCopyBlockInputStream的 copyData 方法构造出 Block: 3. 组装 OutputSt

dbkernel 的博客 140

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

如何为DBX开发JDBC驱动插件:扩展支持更多数据库的开发者指南

DBX是一款15MB的轻量级跨平台数据库客户端,支持MySQL、PostgreSQL、SQLite、Redis、MongoDB、DuckDB、ClickHouse、SQL Server等多种数据库。如果你想让DBX支持更多的数据库类型,或者想要基于JDBC协议为特定数据库开发插件,本文将为你提供完整的开发指南。🔧 ## 为什么需要JDBC驱动插件? DBX默认使用原生Rust驱动来连接各种数

gitblog_00671的博客 478

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

mysql数据库协议..分析【mysql protocol 】

Retrieved from "http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol"MySQL Client/Server Protocol Organization The topic is: the contents of logical packets in MyS

内方外圆 1万+

mysql 协议解析

mysql协议解析

RQV 5865

MySQL8 中文参考(九)

原文:docs.oracle.com/javase/tutorial/reallybigindex.html。

龙哥盟 1223

探索MySQL Protocol Analyzer:揭秘数据库通信的利器

探索MySQL Protocol Analyzer:揭秘数据库通信的利器 在数据库开发和优化的过程中,理解SQL语句如何与数据库交互是至关重要的。GitCode上的项目正是为此目的而生的一个强大工具,它帮助开发者深入解析MySQL协议,进而提升性能、解决各种问题。 项目简介 MysqlProtocolAnalyzer 是一个开源的C#应用,用于解码并可视化MySQL客户端和服务器之间的网络通信数据...

gitblog_00001的博客 471

ClickHouse和他的朋友们(2)MySQL Protocol和Read调用栈

原文出处:https://bohutang.me/2020/06/07/clickhouse-and-friends-mysql-protocol-read-stack/作为一个 OLA...

老叶茶馆 482

MySQL Protocol ,知识体系一共包含哪些部分?底层原理是什么?

MySQL 客户端与服务器之间的二进制通信协议,定义了连接、认证、查询、结果返回的完整流程MySQL Protocol 不是“SQL”,而是“运 SQL 的货车”——它决定了 SQL 如何打包、如何运输、如何卸货。掌握它,你就能真正理解数据库连接的“底层交通规则”。

长风破浪会有时的博客 921

开启MySQL的新篇章:引入Protocol Buffers

???? 开启MySQL的新篇章:引入Protocol Buffers 在数据库领域,MySQL因其稳定性和灵活性而广受赞誉。然而,随着数据交换和应用集成需求的日益增长,我们不断寻求创新以提升其功能边界。今天,我们要向大家隆重介绍一款集成了Google强大Protocol Buffers技术的MySQL版本——这不仅是一次简单的升级,而是对传统数据库通信机制的一次革命性挑战! ????️ 技术革新:Proto...

gitblog_00070的博客 359

idea连接mysql报错: No appropriate protocol (protocol is disabled or cipher suites are inappropriate(已解决)

报错如下: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) The following required algorithms might be disabled: SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize

yunnuo的博客 5万+

mysql网络协议分析

mysql网络协议分析我们从客户端本地登陆一个mysql的用户以及使用mysql命令获得想要的消息.  需要去请求mysql的服务器,这个时候就需要用到mysql的网络通信协议.  当你打算编写数据库的代理服务器,数据库的中间件,这些直接对数据包进行直接操作的组件时,你必须了解到mysql网络通信协议底层的原理.服务器会使用TCP监听本地socket端口或者本地socket连接. 当一个客户端的连...

阿亮的博客 6034

ClickHouse与MySQL之间实时同步数据(MySQL引擎),将MySQL数据实时同步到clickhouse

mysql,clickhouse数据实时同步

奔跑的小番茄 2108

2021-09-13

背景: 随着数据量的上升,OLAP一直是被讨论的话题,虽然druid,kylin能够解决OLAP问题,但是druid,kylin也是需要和hadoop全家桶一起用的,异常的笨重,再说我也搞不定,那只能找我能搞定的技术。故引进clickhoue,关于clickhoue在17年本人就开始关注,并且写了一些入门的介绍,直到19年clickhoue功能慢慢的丰富才又慢慢的关注,并且编写了同步程序,把mysql数据实时同步到clickhoue,并且最终在线上使用起来。 关于clickhouse是什么请自行查阅官网

lcfchan的博客 273

clickhouse 直连mysql_Clickhouse最佳实战之MySQL接口操作ClickHouse及DBeaver工具安装与使用...

Clickhouse最佳实战之MySQL接口操作ClickHouse及Beaver工具安装与使用官方网站:https://clickhouse.tech/docs/zh/interfaces/mysql/​clickhouse.tech此实战主要就是使用Clickhouse提供的MySQL线协议,真实的环境中这种连接Clickhouse的方式比较少用,更多的是使用Clickhouse-client...

weixin_29699041的博客 2073
上一篇: 源码分析 | ClickHouse和他的朋友们(1)编译、开发、测试
下一篇: 源码分析 | ClickHouse和他的朋友们(3)MySQL Protocol和Write调用栈
dbkernel
博客等级 码龄4年 60粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值