NewLife.MySql 采用四层架构,自上而下分为应用层、ADO.NET 标准接口层、连接池层、协议+网络层。核心协议实现集中在 SqlClient 单一类中(约 900 行),整体代码量约 3000 行,极简设计。
┌─────────────────────────────────────────────┐
│ 应用层 (Application) │
│ DAL / XCode / 直接使用 ADO.NET 接口 │
└─────────────────────┬───────────────────────┘
│
┌─────────────────────▼───────────────────────┐
│ ADO.NET 标准接口层 │
│ MySqlConnection MySqlCommand │
│ MySqlDataReader MySqlTransaction │
│ MySqlParameter MySqlParameterCollection │
│ MySqlClientFactory MySqlDataAdapter │
│ MySqlBatch / MySqlBatchCommand (.NET 6+) │
└─────────────────────┬───────────────────────┘
│
┌─────────────────────▼───────────────────────┐
│ 连接池层 (Pool) │
│ MySqlPoolManager MySqlPool │
│ 按连接字符串分池,复用 SqlClient 连接 │
└─────────────────────┬───────────────────────┘
│
┌─────────────────────▼───────────────────────┐
│ 协议层 (Protocol) │
│ SqlClient Authentication │
│ SchemaProvider WelcomeMessage │
│ Response MySqlColumn │
│ BinaryHelper ClientFlags │
└─────────────────────┬───────────────────────┘
│
┌─────────────────────▼───────────────────────┐
│ 网络层 (Network) │
│ TcpClient + NetworkStream │
│ SslStream (可选 TLS 加密) │
└─────────────────────────────────────────────┘
核心类关系
| 类名 | 基类 | 职责 |
|---|
MySqlClientFactory | DbProviderFactory | 工厂类,创建连接/命令/参数等对象,管理连接池 |
MySqlConnection | DbConnection | 数据库连接,管理生命周期和状态 |
MySqlCommand | DbCommand | SQL 命令执行,参数化查询,存储过程调用 |
MySqlDataReader | DbDataReader | 结果集读取,逐行读取数据,多结果集遍历 |
MySqlTransaction | DbTransaction | 事务管理,提交/回滚,自动回滚 |
MySqlParameter | DbParameter | 查询参数,支持输入/输出方向 |
MySqlParameterCollection | DbParameterCollection | 参数集合 |
MySqlConnectionStringBuilder | DbConnectionStringBuilder | 连接字符串解析 |
MySqlDataAdapter | DbDataAdapter | 数据适配器,DataSet/DataTable 填充和更新 |
MySqlBatch (.NET 6+) | DbBatch | ADO.NET 标准批量命令 |
MySqlBatchCommand (.NET 6+) | DbBatchCommand | 批量命令中的单条命令 |
协议层
| 类名 | 职责 |
|---|
SqlClient | 核心协议实现,管理 TCP 连接、收发数据包、协议解析 |
Authentication | MySQL 认证流程(mysql_native_password / caching_sha2_password) |
Response | 响应包封装,判断 OK/Error/EOF |
WelcomeMessage | 握手欢迎消息解析 |
SchemaProvider | Schema 信息查询(数据库/表/列/索引) |
MySqlColumn | 结果集列元数据 |
辅助类
| 类名 | 职责 |
|---|
BinaryHelper | MySQL 协议二进制读写扩展方法 |
MySqlDbType | MySQL 数据类型枚举 |
ClientFlags | 客户端能力标志位 |
ServerStatus / ServerStatusFlags | 服务器状态标志位 |
DbCmd | MySQL 命令类型枚举 |
MySqlException | MySQL 异常类 |
QueryResult / RowResult | 查询结果和行读取结果 |
协议层架构
SqlClient(协议层核心,单一职责)
├── OpenAsync() → TCP 连接 + 握手 + 认证
├── SendPacketAsync() → 帧封装 + 发送
├── ReadPacketAsync() → 帧解析 + 超时控制
├── SendQueryAsync() → COM_QUERY 文本协议
├── PrepareStatementAsync() → COM_STMT_PREPARE
├── ExecuteStatementAsync() → COM_STMT_EXECUTE 二进制协议
├── ExecuteStatementPipelineAsync() → 管道化/串行批量执行
│ ├── ExecutePipelineCoreAsync() → 真管道化(批发批收)
│ └── 串行循环 → 逐条发送+读取
├── BuildExecutePacket() → 构建 EXECUTE 包(与发送解耦)
└── GetResult() / NextRowAsync() / NextBinaryRowAsync() → 响应解析
协议包格式
+-------------------+-------+-----------+
| payload_length | seq | payload |
| 3 bytes | 1byte | N bytes |
+-------------------+-------+-----------+
payload_length:3 字节小端序,最大 16MB(0xFFFFFF)
seq:1 字节序列号,每次请求重置为 0,每个包递增
- 超过 16MB 的数据包自动拆分为多个 16MB 帧
数据类型映射
| MySQL 类型 | MySqlDbType | .NET 类型 |
|---|
| TINYINT | Byte | SByte |
| SMALLINT | Int16 | Int16 |
| MEDIUMINT | Int24 | Int32 |
| INT | Int32 | Int32 |
| BIGINT | Int64 | Int64 |
| FLOAT | Float | Single |
| DOUBLE | Double | Double |
| DECIMAL / NUMERIC | NewDecimal | Decimal |
| VARCHAR / CHAR | VarChar / String | String |
| TEXT (各种) | Text 等 | String |
| BLOB (各种) | Blob 等 | Byte[] |
| DATETIME / TIMESTAMP | DateTime / Timestamp | DateTime |
| DATE / TIME | Date / Time | DateTime |
| BIT | Bit | Boolean |
| JSON | Json | String |
| ENUM | Enum | String |
参数化查询类型映射
| .NET 类型 | SQL 字面量 |
|---|
String | 'hello'(自动转义) |
| 数字类型 | 42 |
Boolean | 1 / 0 |
DateTime / DateTimeOffset | '2025-07-01 12:30:00' |
Byte[] | X'CAFE' |
Guid | '01234567-89ab-cdef-...' |
Enum | 转为数字 |
Single / Double | 往返格式(R) |
Decimal | 原样输出 |
null / DBNull.Value | NULL |
| 参数 | 别名 | 默认值 | 说明 |
|---|
| Server | DataSource, Data Source | - | 服务器地址 |
| Port | - | 3306 | 端口号 |
| Database | - | - | 数据库名 |
| UserID | Uid, User Id, User | - | 用户名 |
| Password | Pass, Pwd | - | 密码 |
| ConnectionTimeout | Connection Timeout | 15 | 连接超时(秒) |
| CommandTimeout | Default Command Timeout | 30 | 命令超时(秒) |
| SslMode | Ssl Mode | None | SSL 模式 |
| UseServerPrepare | Use Server Prepare | false | 全局服务端预编译开关 |
| Pipeline | Pipelining | false | 管道化执行开关 |
| 特性 | MySQL 5.5 | MySQL 5.6 | MySQL 5.7 | MySQL 8.0 | MySQL 8.4 | MySQL 9.0 |
|---|
| 默认认证 | native_password | native_password | native_password | caching_sha2 | caching_sha2 | caching_sha2 |
| COM_RESET_CONNECTION | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ |
| JSON 类型 | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ |
| TLS 1.3 | ✗ | ✗ | ✗ | ✓ (8.0.16+) | ✓ | ✓ |
| mysql_native_password | 默认 | 默认 | 默认 | 可用 | 废弃 | 已移除 |
| 数据库 | 支持状态 | 检测规则 | 说明 |
|---|
| MySQL | ✅ 完整支持 | 标准版本字符串(如 8.0.26) | 5.5 ~ 9.0 全版本 |
| OceanBase | ✅ 完整支持 | 版本含 OceanBase(如 5.7.25-OceanBase-v4.0.0) | 基于版本字符串自动识别 |
| TiDB | ✅ 完整支持 | 版本含 TiDB(如 5.7.25-TiDB-v6.5.2) | 基于版本字符串自动识别 |
| MariaDB | ✅ 基础支持 | - | 缺少 ed25519 认证 |
| 接口 | 方法 | 签名 | 入参 | 出参 | 说明 |
|---|
| MySqlConnection | Open / OpenAsync | void Open() / Task OpenAsync() | - | - | 从连接池获取连接 |
| MySqlConnection | Close / CloseAsync | void Close() / Task CloseAsync() | - | - | 归还连接到连接池 |
| MySqlConnection | ChangeDatabase | void ChangeDatabase(String) | 数据库名 | - | 通过 Close+Reopen 切换 |
| MySqlConnection | GetSchema | DataTable GetSchema(String) | 集合名 | DataTable | 查询元数据 |
| MySqlConnection | BeginTransaction | MySqlTransaction BeginTransaction(IsolationLevel) | 隔离级别 | 事务对象 | 开始事务 |
| MySqlCommand | ExecuteReader | DbDataReader ExecuteReader() | - | DataReader | 执行查询返回结果集 |
| MySqlCommand | ExecuteScalar | Object ExecuteScalar() | - | 第一行第一列 | 执行查询返回单值 |
| MySqlCommand | ExecuteNonQuery | Int32 ExecuteNonQuery() | - | 影响行数 | 执行 DML |
| MySqlCommand | Prepare | void Prepare() | - | - | 服务端预编译 |
| 接口 | 方法 | 签名 | 入参 | 出参 | 说明 |
|---|
| MySqlCommand | ExecuteBatch | Int32 ExecuteBatch(IList<IDictionary<String, Object?>>) | 字典参数集 | 累计影响行数 | 字典参数集批量执行 |
| MySqlCommand | ExecuteBatchAsync | Task<Int32> ExecuteBatchAsync(...) | 字典参数集 | 累计影响行数 | 异步字典参数集批量 |
| MySqlCommand | ExecuteArrayBatch | Int32 ExecuteArrayBatch(Int32) | 执行次数 | 累计影响行数 | 数组绑定批量执行 |
| MySqlCommand | ExecuteArrayBatchAsync | Task<Int32> ExecuteArrayBatchAsync(...) | 执行次数 | 累计影响行数 | 异步数组绑定批量 |
| 接口 | 方法 | 签名 | 说明 |
|---|
| SqlClient | OpenAsync | Task OpenAsync(MySqlConnectionStringBuilder, CancellationToken) | TCP 连接 + 握手 + 认证 |
| SqlClient | SendQueryAsync | Task<QueryResult> SendQueryAsync(String, CancellationToken) | COM_QUERY 文本协议 |
| SqlClient | PrepareStatementAsync | Task<Int32> PrepareStatementAsync(String, CancellationToken) | COM_STMT_PREPARE |
| SqlClient | ExecuteStatementAsync | Task<QueryResult> ExecuteStatementAsync(Int32, MySqlParameterCollection, CancellationToken) | COM_STMT_EXECUTE |
| SqlClient | ExecuteStatementPipelineAsync | Task<Int32> ExecuteStatementPipelineAsync(Int32, IList<MySqlParameterCollection>, Boolean, CancellationToken) | 管道化/串行批量执行 |
| SqlClient | BuildExecutePacket | Byte[] BuildExecutePacket(Int32, MySqlParameterCollection) | 构建 EXECUTE 包(与发送解耦) |
| SqlClient | SetDatabaseAsync | Task SetDatabaseAsync(String, CancellationToken) | COM_INIT_DB 切换数据库 |
| 领域 | 选型 | 理由 |
|---|
| 基础框架 | NewLife.Core | 同为 NewLife 团队出品,提供 ObjectPool / ArrayPool / Pool.StringBuilder 等基础设施 |
| 网络通信 | TcpClient + NetworkStream | 标准 .NET TCP 通信,全框架兼容 |
| TLS 加密 | SslStream | 标准 .NET SSL/TLS 实现,条件编译适配 TLS 1.3 |
| 内存管理 | ArrayPool + OwnerPacket | 零额外分配,减少 GC 压力 |
| 连接池 | ObjectPool<SqlClient> | NewLife.Core 提供的轻量级对象池 |
| 字符串构建 | Pool.StringBuilder | NewLife.Core 提供的池化 StringBuilder |
| 异步模型 | async/await + Task | 全链路真异步,兼容 net45(通过 Microsoft.Bcl.Async) |
| 多目标框架 | net45 / net461 / netstandard2.0 / netstandard2.1 / net6.0 / net10.0 | 覆盖最广的框架兼容性 |
| 开源协议 | MIT | 商用友好,无 GPL 风险 |
| 决策点 | 方案 | 备选方案 | 选择理由 |
|---|
| 参数化查询实现 | 客户端参数替换 | 服务端预编译(COM_STMT_PREPARE) | 减少网络往返,与 MySql.Data 行为一致,兼容性好;预编译作为可选(UseServerPrepare) |
| ChangeDatabase 实现 | Close + Reopen | COM_INIT_DB 命令 | 简单,连接池映射正确,无状态污染风险;COM_INIT_DB 作为低级 API 可选 |
| 批量操作协议 | COM_STMT_PREPARE + COM_STMT_EXECUTE | COM_QUERY 文本协议拼接 | 二进制协议更高效,参数类型精确,无 SQL 注入风险 |
| 管道化执行 | 包构建与发送解耦(BuildExecutePacket + 延迟 Flush) | 逐条发送等响应 | 批量发送减少网络往返,TCP Nagle 合并小包,大数据场景 4~8× 加速 |
| 管道化错误处理 | 失败时继续读取后续响应,最后抛出第一个错误 | 遇错立即中断 | 保持连接状态干净,避免残留数据污染后续操作 |
| 存储过程实现 | SET + CALL + SELECT 多语句 | 逐步发送独立命令 | 利用多语句能力一次网络往返完成,减少延迟 |
| 认证架构 | 内置 Authentication 类 | 插件系统 | 仅需支持两种认证方式,插件系统过度设计;极简实现约 200 行 |
| 连接池实现 | 继承 ObjectPool<SqlClient> | 自定义连接池 | 复用 NewLife.Core 成熟实现,减少代码量;服务器变量缓存 10 分钟额外优化 |
| IO 模型 | 纯 async/await + Task | ValueTask / PipeReader | Task 全框架兼容(含 net45),轻量级定位无需 PipeReader 复杂度 |
| EF Core 支持方式 | 独立包 NewLife.MySql.EntityFrameworkCore | 内置 | 保持核心包轻量,EF Core 用户按需引用 |
项目已基本开发完成,以下为历史任务分解记录。
- 对应功能:F001
- 产出:SqlClient.OpenAsync、WelcomeMessage、BinaryHelper
- 验收:TCP 连接建立,欢迎包解析成功
- 对应功能:F002
- 产出:Authentication.AuthenticateAsync、SHA1 双重哈希
- 验收:MySQL 5.x/8.0 native_password 认证通过
- 对应功能:F003
- 产出:Authentication 扩展 SHA256 + RSA 全量认证
- 验收:MySQL 8.0+ 默认认证通过,含 RSA 公钥请求
- 对应功能:F004
- 产出:MySqlPoolManager、MySqlPool
- 验收:按连接字符串分池,空闲回收,健康检查
- 对应功能:F005
- 产出:MySqlConnectionStringBuilder
- 验收:全部参数别名正确解析
- 对应功能:F006
- 产出:SqlClient SSL 升级逻辑
- 验收:SslMode=Preferred/Required 正常工作
- 对应功能:F007, F012
- 产出:MySqlCommand.ExecuteReaderAsync、MySqlDataReader
- 验收:结果集读取、多结果集遍历、类型映射
- 对应功能:F008, F009
- 产出:MySqlCommand.ExecuteScalarAsync、ExecuteNonQueryAsync
- 验收:单值查询、DML 影响行数
- 对应功能:F010
- 产出:MySqlParameter、MySqlParameterCollection、参数替换逻辑
- 验收:@参数名替换,转义防注入
- 对应功能:F011
- 产出:SqlClient.PrepareStatementAsync、ExecuteStatementAsync
- 验收:COM_STMT_PREPARE/EXECUTE 二进制协议
- 对应功能:F013
- 产出:MySqlTransaction
- 验收:四种隔离级别,自动回滚
- 对应功能:F014
- 产出:MySqlCommand 存储过程分支
- 验收:IN/OUT 参数,多语句执行
- 对应功能:F015
- 产出:MySqlCommand.ExecuteBatchAsync
- 验收:自动 Prepare + Execute × N
- 对应功能:F016
- 产出:MySqlCommand.ExecuteArrayBatchAsync
- 验收:数组参数按索引提取执行
- 对应功能:F017
- 产出:SqlClient.ExecuteStatementPipelineAsync、ExecutePipelineCoreAsync、BuildExecutePacket
- 验收:Pipeline=true 批发批收,加速比 ≥ 4×
- 对应功能:F018
- 产出:SchemaProvider
- 验收:Databases/Tables/Columns/Indexes 查询
- 对应功能:F019
- 产出:MySqlClientFactory
- 验收:XCode DAL 自动识别驱动
- 对应功能:F020
- 产出:MySqlBatch、MySqlBatchCommand
- 验收:.NET 6+ 标准批量 API
- 对应功能:F021
- 产出:MySqlDataAdapter
- 验收:Fill DataTable
- 对应功能:F022
- 产出:DatabaseType 枚举、版本字符串检测
- 验收:OceanBase/TiDB 自动识别
- 对应功能:F023
- 产出:MySqlConnection.ChangeDatabase、SqlClient.SetDatabaseAsync
- 验收:Close+Reopen 切换,连接池映射正确
- 对应功能:F024
- 产出:NewLife.MySql.EntityFrameworkCore 独立项目
- 验收:类型映射、查询翻译、迁移支持
| 风险 | 影响 | 缓解措施 |
|---|
| MySQL 9.0 移除 mysql_native_password | 仅支持 caching_sha2_password 的环境下老客户端无法连接 | 已实现 caching_sha2_password 认证,含 RSA 全量认证和 Auth Switch |
| 管道化执行中途失败 | 连接状态可能不一致,后续操作异常 | 失败时继续读取后续响应保持连接干净,最后抛出第一个错误 |
| 大包超过 max_allowed_packet | 多行 VALUES 或大批量参数替换可能超限 | 客户端参数替换模式需注意 SQL 长度;预编译+二进制协议不受影响 |
| net45 异步兼容性 | .NET Framework 4.5 异步支持有限 | 依赖 Microsoft.Bcl.Async,条件编译适配 |
| 连接池状态污染 | 使用 SetDatabaseAsync 后归还连接可能污染池 | ChangeDatabase 默认使用 Close+Reopen 避免污染;SetDatabaseAsync 仅作为低级 API |
| EF Core 版本演进 | EF Core 新版本可能引入 breaking change | 独立包隔离,不影响核心驱动 |
Client Server
│ │
│◄──── Welcome Packet ──────────│ 服务器发送欢迎消息(协议版本/能力/种子)
│ │
│ [可选] SSL Request ─────────►│ 如果 SslMode != None
│◄──── TLS Handshake ──────────►│ 升级为加密连接
│ │
│ Auth Response ──────────────►│ 发送认证信息(用户名/加密密码/数据库)
│◄──── OK / Auth Switch ───────│ 认证结果(可能需要切换认证方式)
│ │
│ [可选] RSA 公钥请求 ─────────►│ caching_sha2_password 全量认证
│◄──── RSA 公钥 ───────────────│
│ 加密密码 ───────────────────►│
│◄──── OK ─────────────────────│
│ │
│ SHOW VARIABLES ─────────────►│ 获取服务器变量配置
│◄──── Result Set ─────────────│ max_allowed_packet / charset 等
│ │
Client Server
│ │
│ COM_QUERY(SQL) ─────────────►│ 发送 SQL 查询
│ │
│ [查询结果] │
│◄──── Column Count ───────────│ 列数量
│◄──── Column Definitions ─────│ 列定义 × N
│◄──── EOF ────────────────────│ 列定义结束
│◄──── Row Data ───────────────│ 行数据 × M(文本协议,每列 length-encoded string)
│◄──── EOF ────────────────────│ 结果集结束(状态标志含 MORE_RESULTS 标志)
│ │
│ [非查询结果] │
│◄──── OK Packet ──────────────│ affected_rows + last_insert_id + status_flags
│ │
Client Server
│ │
│ COM_QUERY(SQL1;SQL2;SQL3) ──►│ 发送多条 SQL(分号分隔)
│ │
│◄──── Result1 (OK/ResultSet) ─│ 第一条 SQL 结果,status_flags 含 MORE_RESULTS
│◄──── Result2 (OK/ResultSet) ─│ 第二条 SQL 结果
│◄──── Result3 (OK/ResultSet) ─│ 第三条 SQL 结果,status_flags 不含 MORE_RESULTS
│ │
Client Server
│ │
│ CALL proc(@p1, @p2) ───────►│ 调用存储过程
│ │
│◄──── ResultSet(s) ───────────│ 过程中的 SELECT 结果(0~N 个)
│◄──── OK Packet ──────────────│ 最终状态,status_flags 含 MORE_RESULTS
│◄──── OK Packet ──────────────│ CALL 语句本身的 OK 包
│ │
│ [读取输出参数] │
│ SELECT @p2 ─────────────────►│ 读取 OUT 参数值
│◄──── ResultSet ──────────────│
│ │
Client Server
│ │
│ SET TRANSACTION ... ────────►│ 设置隔离级别
│◄──── OK ─────────────────────│
│ │
│ BEGIN ──────────────────────►│ 开始事务
│◄──── OK ─────────────────────│
│ │
│ INSERT/UPDATE/DELETE ───────►│ 业务 SQL
│◄──── OK ─────────────────────│
│ │
│ COMMIT / ROLLBACK ──────────►│ 提交或回滚
│◄──── OK ─────────────────────│
│ │
串行模式(默认)
$ \text{Client} \text{Server} │ │ │ \text{COM\_STMT\_EXECUTE}(1) ───────►│ 发送第 1 组参数 │◄──── \text{OK} ─────────────────────│ 接收第 1 个响应 │ \text{COM\_STMT\_EXECUTE}(2) ───────►│ 发送第 2 组参数 │◄──── \text{OK} ─────────────────────│ 接收第 2 个响应 │ \text{COM\_STMT\_EXECUTE}(\text{N}) ───────►│ 发送第 \text{N} 组参数 │◄──── \text{OK} ─────────────────────│ 接收第 \text{N} 个响应 │ │ │ 耗时 ≈ \text{N} \times (发送延迟 + 处理时间 + 接收延迟) $
Client Server
│ │
│ ── Phase 1: 批量发送 ── │
│ COM_STMT_EXECUTE(1) ───────►│ 连续发送,不等响应
│ COM_STMT_EXECUTE(2) ───────►│ TCP 协议栈合并小包
│ COM_STMT_EXECUTE(3) ───────►│
│ ... │
│ COM_STMT_EXECUTE(N) ───────►│ 最后一个包 Flush
│ │
│ ── Phase 2: 批量读取 ── │ 服务器按顺序处理并返回
│◄──── OK(1) ──────────────────│ 逐个读取 OK 包
│◄──── OK(2) ──────────────────│ 累加 affected_rows
│◄──── OK(3) ──────────────────│
│ ... │
│◄──── OK(N) ──────────────────│
│ │
│ 耗时 ≈ 批量发送时间 + N × 处理时间 + 批量接收时间
MySqlClientFactory
└── MySqlPoolManager(单例,管理所有连接池)
└── MySqlPool(按连接字符串分组)
├── SqlClient #1 (active)
├── SqlClient #2 (idle)
└── SqlClient #N ...
- 继承
NewLife.Collections.ObjectPool<SqlClient>
- 按连接字符串哈希分池,相同连接字符串共用同一个池
- 默认最小连接数 10,最大 100000
- 空闲超时 30 秒,全空闲超时 300 秒
- 获取连接时验证可用性(
Reset 检查 + Active 状态检查)
- 归还时连接保持打开状态以便复用
- 服务器变量缓存 10 分钟,减少
SHOW VARIABLES 查询
MySqlPoolManager 使用完整连接字符串作为 Key。ChangeDatabase 通过 Close+Reopen 实现:
| 步骤 | 操作 | 连接字符串 | 连接池 |
|---|
| 1 | Open() | ...Database=db1... | Pool1 |
| 2 | ChangeDatabase("db2") | | |
| 3 | ↳ Close() | | 归还到 Pool1 |
| 4 | ↳ 改 Setting.Database | ...Database=db2... | - |
| 5 | ↳ Open() | | 从 Pool2 获取 |
每个连接池中的连接保持一致的数据库状态,避免污染。
| 认证方式 | 引入版本 | 默认版本 | 实现要点 |
|---|
mysql_native_password | MySQL 4.1 | 5.x~5.7 | SHA1 双重哈希,20 字节响应 |
caching_sha2_password | MySQL 8.0 | 8.0+ | SHA256 哈希,首次需 RSA/TLS 传输密码 |
认证流程:服务器欢迎包 → 客户端计算密码哈希 → 发送认证响应 → 处理 Auth Switch(0xFE)→ caching_sha2 缓存未命中时 RSA 公钥加密传输。
CommandText 转换为 CALL proc_name(@p1, @p2, ...) 语句
- 输入参数通过
SET @p1=value 预先设置为 MySQL 用户变量
- 输出参数通过
SELECT @p2 在 CALL 执行后读取
- 利用多语句能力一次发送
SET...;CALL...;SELECT...
ExecuteBatch / ExecuteArrayBatch
│
├── 自动 Prepare(若未预编译)
│ └── ConvertToPositionalParameters → PrepareStatementAsync
│
├── 提取每组参数 → MySqlParameterCollection 列表
│ ├── ExecuteBatch: 从字典提取
│ └── ExecuteArrayBatch: 从数组中按索引提取
│
├── 调用 ExecuteStatementPipelineAsync
│ ├── Pipeline=true: BuildExecutePacket×N → SendPacket(flush:false)×N → Flush → ReadPacket×N
│ └── Pipeline=false: (ExecuteStatement → ReadPacket) × N
│
└── 自动 Unprepare(若本次自动预编译的)
ExecuteReaderAsync 返回时:
┌────────────────────────────────┐
│ Reader 定位在第一个结果 │
│ _FieldCount = 0 或 > 0 │
│ _hasMoreResults = true/false │
│ _allRowsConsumed = true │
└────────────────────────────────┘
↓
调用 ReadAsync()
↓
┌────────────────────────────────┐
│ 如果 FieldCount > 0 │
│ 读取一行数据,填充 _Values │
│ _allRowsConsumed = false │
└────────────────────────────────┘
↓
调用 NextResultAsync()
↓
┌────────────────────────────────┐
│ 消费当前结果集的剩余行 │
│ 读取下一个结果 │
│ 更新 _FieldCount │
│ 累加 _RecordsAffected │
│ 更新 _hasMoreResults │
└────────────────────────────────┘
| 框架 | 说明 |
|---|
net45 | .NET Framework 4.5 |
net461 | .NET Framework 4.6.1 |
netstandard2.0 | .NET Standard 2.0 |
netstandard2.1 | .NET Standard 2.1(支持异步 Dispose、CloseAsync) |
net6.0 | .NET 6(额外支持 DbBatch API) |
net10.0 | .NET 10(最新框架,最优性能) |
条件编译符号:NETFRAMEWORK、NET45、NETSTANDARD2_1_OR_GREATER、NET5_0_OR_GREATER、NET6_0_OR_GREATER
| 架构维度 | NewLife.MySql | MySqlConnector | MySql.Data (Oracle) |
|---|
| 架构层次 | 4 层 | 5 层(含中间件层) | 4 层 |
| 协议实现 | 单一 SqlClient 类 | MySqlSession + MySqlProtocolSerializer 分离 | NativeDriver 单体 |
| IO 模型 | 纯 async/await | 纯 async/await + ValueTask | 同步为主 |
| 内存管理 | ArrayPool + OwnerPacket | ArrayPool + SequenceReader | 传统 byte[] 分配 |
| 连接池 | ObjectPool<SqlClient> | 自定义 ConnectionPool | 自定义连接池 |
| 代码行数 | ~3000 行 | ~30000 行 | ~50000 行 |
| 批量方案 | NewLife.MySql | MySqlConnector | MySql.Data |
|---|
| 字典参数集批量 | ✅ ExecuteBatch | ❌ | ❌ |
| 数组绑定批量 | ✅ ExecuteArrayBatch | ❌ | ❌ |
| 管道化执行 | ✅ Pipeline=true | ❌ | ❌ |
| DbBatch | ✅ (.NET 6+) | ✅ (.NET 6+) | ❌ |
| BulkCopy | ❌ | ✅ | ❌ |
管道化+事务 vs 逐行基线(.NET 10 + MySQL 8.0.26 本机):
| 场景 | 逐行基线 | 管道化+事务 | 加速比 |
|---|
| 1,000 行 INSERT | 437ms | 54ms | 8.1× |
| 10,000 行 INSERT | 3,150ms | 680ms | 4.6× |
| 10,000 行 UPDATE | 3,469ms | 757ms | 4.6× |
| 10,000 行 DELETE | 3,351ms | 673ms | 5.0× |
三驱动对比(10,000 行批量操作):
| 操作 | NewLife Pipeline(tx) | MySql.Data Batch(tx) | MySqlConnector Batch(tx) | NewLife 加速比 |
|---|
| INSERT | 899ms | 1,927ms | 1,906ms | 2.1× |
| UPDATE | 710ms | 2,265ms | 2,041ms | 2.9× |
| DELETE | 661ms | 1,961ms | 1,767ms | 2.7× |
详细数据参见 性能测试报告。
| 场景 | 推荐驱动 | 理由 |
|---|
| 大数据批量 DML | NewLife.MySql | 管道化 + 数组绑定,性能最优 |
| 国产化/信创 | NewLife.MySql | 纯国产、MIT、零第三方依赖 |
| XCode ORM 项目 | NewLife.MySql | 原生集成,无缝对接 |
| 轻量级微服务 | NewLife.MySql | 代码精简,启动快 |
| EF Core 项目 | MySqlConnector | Pomelo.EF 支持 |
| 需要 BulkCopy | MySqlConnector | MySqlBulkCopy API |
| 需要压缩协议 | MySqlConnector | 内置压缩支持 |