概述

MySQL存储引擎接口层是数据库系统的核心抽象层,它定义了统一的存储引擎API,使得MySQL能够支持多种不同的存储引擎。本文将深入分析这一接口层的设计原理、核心数据结构和实现机制。

1. 存储引擎接口层整体架构

1.1 接口层设计原则

MySQL存储引擎接口层采用经典的抽象工厂模式:

  • 统一接口:所有存储引擎实现相同的抽象接口
  • 插件化架构:支持动态加载和卸载存储引擎
  • 透明性:上层SQL层无需关心具体存储引擎实现
  • 扩展性:易于添加新的存储引擎

1.2 存储引擎接口层架构图

graph TB subgraph "MySQL存储引擎接口层架构" subgraph "SQL层" SQLLayer[SQL执行器] QueryOpt[查询优化器] Parser[解析器] end subgraph "存储引擎接口层 - Handler Interface" subgraph "核心抽象接口" HandlerClass[Handler抽象类] HandlertonStruct[handlerton结构体] PluginInterface[插件接口] end subgraph "插件管理系统" PluginMgr[插件管理器] PluginLoader[插件加载器] PluginRegistry[插件注册表] VersionCheck[版本检查] end subgraph "表操作抽象" TableOpen[表打开/关闭] RecordOps[记录操作] IndexOps[索引操作] ScanOps[扫描操作] TxnOps[事务操作] end subgraph "系统接口" SystemVars[系统变量] StatusVars[状态变量] InfoSchema[信息模式] AdminCmds[管理命令] end end subgraph "具体存储引擎" subgraph "InnoDB引擎" InnoHandler[ha_innobase] InnoHton[innobase_hton] InnoPlugin[InnoDB插件] end subgraph "MyISAM引擎" MyisamHandler[ha_myisam] MyisamHton[myisam_hton] MyisamPlugin[MyISAM插件] end subgraph "Memory引擎" MemHandler[ha_heap] MemHton[heap_hton] MemPlugin[Memory插件] end subgraph "其他引擎" CSVHandler[ha_tina] ArchiveHandler[ha_archive] OtherEngines[...] end end subgraph "文件系统层" DataFiles[数据文件] IndexFiles[索引文件] LogFiles[日志文件] MetaFiles[元数据文件] end end %% 连接关系 SQLLayer --> HandlerClass QueryOpt --> HandlerClass Parser --> PluginInterface HandlerClass --> HandlertonStruct HandlertonStruct --> PluginInterface PluginInterface --> PluginMgr PluginMgr --> PluginLoader PluginLoader --> PluginRegistry PluginRegistry --> VersionCheck HandlerClass --> TableOpen TableOpen --> RecordOps RecordOps --> IndexOps IndexOps --> ScanOps ScanOps --> TxnOps SystemVars --> InfoSchema StatusVars --> InfoSchema InfoSchema --> AdminCmds HandlerClass --> InnoHandler HandlerClass --> MyisamHandler HandlerClass --> MemHandler HandlerClass --> CSVHandler InnoHandler --> InnoHton MyisamHandler --> MyisamHton MemHandler --> MemHton InnoHton --> InnoPlugin MyisamHton --> MyisamPlugin MemHton --> MemPlugin InnoHandler --> DataFiles MyisamHandler --> DataFiles MemHandler --> IndexFiles CSVHandler --> LogFiles style HandlerClass fill:#e1f5fe style HandlertonStruct fill:#f3e5f5 style PluginMgr fill:#e8f5e8 style InnoHandler fill:#fff3e0 style DataFiles fill:#fce4ec

2. Handler抽象类深度解析

2.1 Handler类核心定义

Handler类是所有存储引擎必须实现的抽象基类:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
/**
 * Handler类:MySQL存储引擎接口的抽象基类
 * 定义了所有存储引擎必须实现的接口方法
 * 为SQL层提供统一的数据访问接口
 */
class handler {
protected:
    // 基础成员变量
    TABLE_SHARE *table_share;    ///< 表共享信息,包含表的元数据
    TABLE *table;                ///< 当前操作的表对象指针
    handlerton *ht;             ///< 指向存储引擎句柄的指针
    
    // 记录定位和引用
    uchar *ref;                  ///< 当前记录的物理位置引用
    uchar *dup_ref;             ///< 重复键检测时使用的引用
    uint ref_length;            ///< 记录引用的字节长度
    
    // 索引相关
    uint active_index;          ///< 当前活跃索引的编号(MAX_KEY表示无索引)
    uint keyread;               ///< 仅读索引标志位掩码
    
    // 统计信息
    ha_statistics stats;         ///< 表统计信息(记录数、索引大小等)
    ha_rows estimation_rows_to_insert; ///< 预估要插入的行数
    
    // 性能监控相关  
    PSI_table *m_psi;           ///< Performance Schema表接口
    PSI_table_locker_state m_psi_locker_state; ///< PSI状态
    
public:
    /**
     * Handler构造函数
     * @param hton 存储引擎句柄指针
     * @param share 表共享信息指针
     */
    handler(handlerton *hton_arg, TABLE_SHARE *share_arg)
        : table_share(share_arg), table(nullptr), ht(hton_arg),
          ref(nullptr), dup_ref(nullptr), ref_length(sizeof(my_off_t)),
          active_index(MAX_KEY), keyread(0) {
        // 初始化统计信息
        memset(&stats, 0, sizeof(stats));
        estimation_rows_to_insert = 0;
        m_psi = nullptr;
    }
    
    /**
     * 虚析构函数,确保派生类正确析构
     */
    virtual ~handler() = default;
    
    // ========== 表生命周期管理接口 ==========
    
    /**
     * 打开表文件
     * @param name 表名(包含路径)
     * @param mode 打开模式(O_RDONLY, O_RDWR等)
     * @param test_if_locked 是否测试表锁定状态
     * @return 0表示成功,非0表示错误码
     */
    virtual int open(const char *name, int mode, uint test_if_locked) = 0;
    
    /**
     * 关闭表文件,释放相关资源
     * @return 0表示成功,非0表示错误码
     */
    virtual int close() = 0;
    
    /**
     * 创建新表
     * @param name 表名
     * @param table_arg 表结构信息
     * @param ha_create_info 创建参数
     * @return 0表示成功,非0表示错误码
     */
    virtual int create(const char *name, TABLE *table_arg,
                      HA_CREATE_INFO *ha_create_info,
                      dd::Table *table_def) {
        // 默认实现返回不支持
        return HA_ERR_WRONG_COMMAND;
    }
    
    /**
     * 删除表文件
     * @param name 表名
     * @return 0表示成功,非0表示错误码
     */
    virtual int delete_table(const char *name, const dd::Table *table_def) {
        return HA_ERR_WRONG_COMMAND;
    }
    
    // ========== 数据扫描接口 ==========
    
    /**
     * 初始化全表扫描
     * @param scan true表示进行扫描,false表示仅初始化
     * @return 0表示成功,非0表示错误码
     */
    virtual int rnd_init(bool scan = true) = 0;
    
    /**
     * 结束全表扫描,释放相关资源
     * @return 0表示成功,非0表示错误码
     */
    virtual int rnd_end() = 0;
    
    /**
     * 读取下一条记录(全表扫描)
     * @param buf 用于存储记录数据的缓冲区
     * @return 0表示成功,HA_ERR_END_OF_FILE表示扫描结束,其他表示错误
     */
    virtual int rnd_next(uchar *buf) = 0;
    
    /**
     * 根据位置读取指定记录
     * @param buf 用于存储记录数据的缓冲区
     * @param pos 记录位置信息
     * @return 0表示成功,HA_ERR_KEY_NOT_FOUND表示记录不存在
     */
    virtual int rnd_pos(uchar *buf, uchar *pos) = 0;
    
    /**
     * 获取当前记录的位置信息
     * @param ref 用于存储位置信息的缓冲区
     */
    virtual void position(const uchar *record) = 0;
    
    // ========== 索引操作接口 ==========
    
    /**
     * 初始化索引扫描
     * @param idx 索引编号
     * @param sorted 是否需要排序结果
     * @return 0表示成功,非0表示错误码
     */
    virtual int index_init(uint idx, bool sorted = false) = 0;
    
    /**
     * 结束索引扫描
     * @return 0表示成功,非0表示错误码
     */
    virtual int index_end() = 0;
    
    /**
     * 根据键值读取记录
     * @param buf 用于存储记录数据的缓冲区
     * @param key 搜索键值
     * @param key_len 键值长度
     * @param find_flag 查找标志(HA_READ_KEY_EXACT等)
     * @return 0表示成功,HA_ERR_KEY_NOT_FOUND表示未找到
     */
    virtual int index_read(uchar *buf, const uchar *key, uint key_len,
                          enum ha_rkey_function find_flag) = 0;
                          
    /**
     * 读取下一条索引记录
     * @param buf 用于存储记录数据的缓冲区
     * @return 0表示成功,HA_ERR_END_OF_FILE表示扫描结束
     */
    virtual int index_next(uchar *buf) = 0;
    
    /**
     * 读取前一条索引记录
     * @param buf 用于存储记录数据的缓冲区
     * @return 0表示成功,HA_ERR_END_OF_FILE表示到达开始
     */
    virtual int index_prev(uchar *buf) = 0;
    
    /**
     * 读取第一条索引记录
     * @param buf 用于存储记录数据的缓冲区
     * @return 0表示成功,HA_ERR_END_OF_FILE表示索引为空
     */
    virtual int index_first(uchar *buf) = 0;
    
    /**
     * 读取最后一条索引记录
     * @param buf 用于存储记录数据的缓冲区
     * @return 0表示成功,HA_ERR_END_OF_FILE表示索引为空
     */
    virtual int index_last(uchar *buf) = 0;
    
    // ========== 数据修改接口 ==========
    
    /**
     * 插入新记录
     * @param buf 要插入的记录数据
     * @return 0表示成功,HA_ERR_FOUND_DUPP_KEY表示重复键错误
     */
    virtual int write_row(uchar *buf) = 0;
    
    /**
     * 更新当前记录
     * @param old_data 旧记录数据
     * @param new_data 新记录数据
     * @return 0表示成功,非0表示错误码
     */
    virtual int update_row(const uchar *old_data, const uchar *new_data) = 0;
    
    /**
     * 删除当前记录
     * @param buf 要删除的记录数据
     * @return 0表示成功,非0表示错误码
     */
    virtual int delete_row(const uchar *buf) = 0;
    
    // ========== 事务接口 ==========
    
    /**
     * 开始事务
     * @param thd 线程句柄
     * @param level 事务隔离级别
     * @return 0表示成功,非0表示错误码
     */
    virtual int start_stmt(THD *thd, thr_lock_type lock_type) { return 0; }
    
    /**
     * 外部锁定(表级锁)
     * @param thd 线程句柄
     * @param lock_type 锁类型
     * @return 0表示成功,非0表示错误码
     */
    virtual int external_lock(THD *thd, int lock_type) { return 0; }
    
    // ========== 统计信息接口 ==========
    
    /**
     * 获取表统计信息
     * @param flag 信息类型标志
     * @return 0表示成功,非0表示错误码
     */
    virtual int info(uint flag) = 0;
    
    /**
     * 获取记录数估算值
     * @return 表中的记录数
     */
    virtual ha_rows records() { return stats.records; }
    
    /**
     * 估算索引基数
     * @param inx 索引编号
     * @return 索引的基数(唯一值数量)
     */
    virtual ha_rows index_cardinality(uint inx) {
        return stats.records / 10; // 简单估算
    }
    
    // ========== 能力标志接口 ==========
    
    /**
     * 获取表级功能标志
     * @return 功能标志位掩码
     */
    virtual Table_flags table_flags() const = 0;
    
    /**
     * 获取索引级功能标志
     * @param idx 索引编号
     * @param part 索引部分编号
     * @param all_parts 是否包含所有部分
     * @return 索引功能标志位掩码
     */
    virtual ulong index_flags(uint idx, uint part, bool all_parts) const = 0;
    
    /**
     * 获取最大键长度
     * @return 支持的最大键长度(字节)
     */
    virtual uint max_key_length() const { return 0; }
    
    /**
     * 获取最大键部分数量
     * @return 支持的最大键部分数
     */
    virtual uint max_key_parts() const { return 0; }
    
    // ========== 批量操作接口 ==========
    
    /**
     * 开始批量插入
     * @param rows 预估插入行数
     * @param flags 插入标志
     */
    virtual void start_bulk_insert(ha_rows rows, uint flags = 0) {
        estimation_rows_to_insert = rows;
    }
    
    /**
     * 结束批量插入
     * @return 0表示成功,非0表示错误码
     */
    virtual int end_bulk_insert() { 
        estimation_rows_to_insert = 0;
        return 0; 
    }
    
    // ========== 工具方法 ==========
    
    /**
     * 获取存储引擎名称
     * @return 存储引擎名称字符串
     */
    virtual const char *table_type() const {
        return hton_name(ht)->str;
    }
    
    /**
     * 检查是否支持指定操作
     * @param operation 操作类型
     * @return true表示支持,false表示不支持
     */
    bool check_if_supported_operation(enum ha_base_keytype operation) const {
        return (table_flags() & operation) != 0;
    }
    
    /**
     * 打印错误信息
     * @param error 错误码
     * @param errflag 错误标志
     */
    virtual void print_error(int error, myf errflag);
    
protected:
    /**
     * 获取线程句柄
     * @return 当前线程的THD指针
     */
    THD *ha_thd() const;
    
    /**
     * 更新统计信息
     */
    void update_statistics() {
        // 更新访问次数、I/O次数等统计信息
        stats.data_file_length = get_data_file_size();
        stats.index_file_length = get_index_file_size();
        stats.records = estimate_record_count();
    }
    
    /**
     * 获取数据文件大小(由派生类实现)
     */
    virtual my_off_t get_data_file_size() const { return 0; }
    
    /**
     * 获取索引文件大小(由派生类实现)
     */
    virtual my_off_t get_index_file_size() const { return 0; }
    
    /**
     * 估算记录数(由派生类实现)
     */
    virtual ha_rows estimate_record_count() const { return HA_POS_ERROR; }
};

2.2 Handler错误码定义

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
 * Handler接口错误码定义
 * 这些错误码用于统一不同存储引擎的错误报告
 */
enum ha_base_keytype {
    // 成功状态
    HA_ERR_OK = 0,                    ///< 操作成功
    
    // 通用错误
    HA_ERR_KEY_NOT_FOUND = 120,       ///< 键值未找到
    HA_ERR_FOUND_DUPP_KEY = 121,      ///< 发现重复键
    HA_ERR_RECORD_CHANGED = 123,      ///< 记录已被修改(乐观锁)
    HA_ERR_WRONG_INDEX = 124,         ///< 错误的索引
    HA_ERR_CRASHED = 126,             ///< 表文件损坏
    HA_ERR_WRONG_IN_RECORD = 127,     ///< 记录格式错误
    HA_ERR_OUT_OF_MEM = 128,          ///< 内存不足
    
    // 文件操作错误
    HA_ERR_NOT_A_TABLE = 130,         ///< 不是有效的表文件
    HA_ERR_WRONG_COMMAND = 131,       ///< 不支持的操作
    HA_ERR_OLD_FILE = 132,            ///< 旧文件格式
    HA_ERR_NO_ACTIVE_RECORD = 133,    ///< 没有活跃记录
    HA_ERR_RECORD_DELETED = 134,      ///< 记录已删除
    HA_ERR_RECORD_FILE_FULL = 135,    ///< 记录文件已满
    HA_ERR_INDEX_FILE_FULL = 136,     ///< 索引文件已满
    HA_ERR_END_OF_FILE = 137,         ///< 到达文件末尾
    HA_ERR_UNSUPPORTED = 138,         ///< 不支持的功能
    
    // 锁相关错误
    HA_ERR_TO_BIG_ROW = 139,          ///< 行太大
    HA_ERR_WRONG_CREATE_OPTION = 140, ///< 错误的创建选项
    HA_ERR_FOUND_DUPP_UNIQUE = 141,   ///< 唯一索引重复
    HA_ERR_UNKNOWN_CHARSET = 142,     ///< 未知字符集
    HA_ERR_WRONG_MRG_TABLE_DEF = 143, ///< 错误的合并表定义
    HA_ERR_CRASHED_ON_REPAIR = 144,   ///< 修复时表损坏
    HA_ERR_CRASHED_ON_USAGE = 145,    ///< 使用时表损坏
    HA_ERR_LOCK_WAIT_TIMEOUT = 146,   ///< 锁等待超时
    HA_ERR_LOCK_TABLE_FULL = 147,     ///< 锁表已满
    HA_ERR_READ_ONLY_TRANSACTION = 148, ///< 只读事务
    
    // 死锁和事务错误
    HA_ERR_LOCK_DEADLOCK = 149,       ///< 检测到死锁
    HA_ERR_CANNOT_ADD_FOREIGN = 150,  ///< 无法添加外键
    HA_ERR_NO_REFERENCED_ROW = 151,   ///< 没有被引用行
    HA_ERR_ROW_IS_REFERENCED = 152,   ///< 行被引用中
    HA_ERR_NO_SAVEPOINT = 153,        ///< 没有保存点
    HA_ERR_NON_UNIQUE_BLOCK_SIZE = 154, ///< 非唯一块大小
    HA_ERR_NO_SUCH_TABLE = 155,       ///< 表不存在
    HA_ERR_TABLE_EXIST = 156,         ///< 表已存在
    HA_ERR_NO_CONNECTION = 157,       ///< 没有连接
    HA_ERR_NULL_IN_SPATIAL = 158,     ///< 空间索引中有NULL值
    HA_ERR_TABLE_DEF_CHANGED = 159,   ///< 表定义已改变
    HA_ERR_NO_PARTITION_FOUND = 160,  ///< 未找到分区
    HA_ERR_RBR_LOGGING_FAILED = 161,  ///< RBR日志记录失败
    HA_ERR_DROP_INDEX_FK = 162,       ///< 不能删除外键索引
    HA_ERR_FOREIGN_DUPLICATE_KEY = 163, ///< 外键重复键
    HA_ERR_TABLE_NEEDS_UPGRADE = 164, ///< 表需要升级
    HA_ERR_TABLE_READONLY = 165,      ///< 表只读
    HA_ERR_AUTOINC_READ_FAILED = 166, ///< 自增读取失败
    HA_ERR_AUTOINC_ERANGE = 167,      ///< 自增值超出范围
    HA_ERR_GENERIC = 168,             ///< 通用错误
    HA_ERR_RECORD_IS_THE_SAME = 169,  ///< 记录相同
    HA_ERR_LOGGING_IMPOSSIBLE = 170,  ///< 无法记录日志
    HA_ERR_CORRUPT_EVENT = 171,       ///< 损坏事件
    HA_ERR_ROWS_EVENT_APPLY = 172,    ///< 行事件应用失败
    HA_ERR_FILE_TOO_SHORT = 173,      ///< 文件太短
    HA_ERR_WRONG_CRC = 174,           ///< CRC错误
    HA_ERR_TOO_MANY_CONCURRENT_TRXS = 175, ///< 并发事务太多
    HA_ERR_NOT_IN_LOCK_PARTITIONS = 176,   ///< 不在锁定分区中
    HA_ERR_INDEX_COL_TOO_LONG = 177,       ///< 索引列太长
    HA_ERR_INDEX_CORRUPT = 178,            ///< 索引损坏
    HA_ERR_UNDO_REC_TOO_BIG = 179,         ///< Undo记录太大
    HA_ERR_TABLE_IN_FK_CHECK = 180,        ///< 表在外键检查中
    HA_ERR_TABLESPACE_EXISTS = 181,        ///< 表空间已存在
    HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT = 182, ///< 全文搜索结果超限
    HA_ERR_TEMP_FILE_WRITE_FAILURE = 183,  ///< 临时文件写入失败
    HA_ERR_INNODB_FORCED_RECOVERY = 184,   ///< InnoDB强制恢复模式
    HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE = 185, ///< 短语中单词太多
    
    // 新增错误码
    HA_ERR_LAST = 186                 ///< 最后一个错误码
};

/**
 * 将Handler错误码转换为MySQL错误码
 * @param error Handler错误码
 * @return 对应的MySQL错误码
 */
int ha_error_to_mysql_error(int error) {
    switch (error) {
        case HA_ERR_KEY_NOT_FOUND:
            return ER_KEY_NOT_FOUND;
        case HA_ERR_FOUND_DUPP_KEY:
            return ER_DUP_KEY;
        case HA_ERR_RECORD_CHANGED:
            return ER_CHECKREAD;
        case HA_ERR_WRONG_INDEX:
            return ER_WRONG_MRG_TABLE;
        case HA_ERR_CRASHED:
            return ER_NOT_KEYFILE;
        case HA_ERR_OUT_OF_MEM:
            return ER_OUT_OF_RESOURCES;
        case HA_ERR_WRONG_COMMAND:
            return ER_ILLEGAL_HA;
        case HA_ERR_OLD_FILE:
            return ER_OLD_KEYFILE;
        case HA_ERR_UNSUPPORTED:
            return ER_UNSUPPORTED_EXTENSION;
        case HA_ERR_LOCK_WAIT_TIMEOUT:
            return ER_LOCK_WAIT_TIMEOUT;
        case HA_ERR_LOCK_DEADLOCK:
            return ER_LOCK_DEADLOCK;
        default:
            return ER_GET_ERRNO;
    }
}

3. handlerton结构体深度解析

3.1 handlerton核心定义

handlerton结构体定义了存储引擎的全局接口和属性:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
/**
 * handlerton:存储引擎的全局描述符
 * 包含存储引擎的全局函数指针、属性和状态信息
 * 每个存储引擎有且仅有一个handlerton实例
 */
struct handlerton {
    // 基础信息
    const char *name;               ///< 存储引擎名称
    SHOW_COMP_OPTION state;        ///< 引擎状态(SHOW_OPTION_YES/NO/DISABLED)
    const char *comment;           ///< 引擎描述信息
    uint db_type;                  ///< 数据库类型ID(向后兼容)
    
    // 插件信息
    plugin_ref plugin_ref;         ///< 插件引用
    uint slot;                     ///< 在hton数组中的槽位编号
    uint32 license;                ///< 许可证类型
    void *data;                    ///< 引擎私有数据指针
    
    // 能力标志
    uint32 flags;                  ///< 引擎功能标志位
    uint32 system_database_flag;   ///< 系统数据库标志
    
    // ========== 生命周期管理函数 ==========
    
    /**
     * 初始化存储引擎
     * @param hton handlerton指针
     * @return 0表示成功,非0表示失败
     */
    int (*init)(handlerton *hton);
    
    /**
     * 清理存储引擎,释放全局资源
     * @param hton handlerton指针
     * @return 0表示成功,非0表示失败
     */
    int (*close)(handlerton *hton);
    
    /**
     * 服务器启动后的初始化
     * 在所有插件加载完成后调用
     */
    void (*post_ddl)(THD *thd);
    
    /**
     * 服务器关闭前的清理
     */
    void (*pre_shutdown)(void);
    
    // ========== Handler实例管理 ==========
    
    /**
     * 创建Handler实例
     * @param hton handlerton指针
     * @param share 表共享信息
     * @param mem_root 内存分配器
     * @return 新创建的Handler实例指针
     */
    handler *(*create)(handlerton *hton, TABLE_SHARE *share, 
                      bool partitioned, MEM_ROOT *mem_root);
                      
    /**
     * 销毁Handler实例
     * @param handler 要销毁的Handler指针
     */
    void (*destroy)(handler *handler);
    
    // ========== 事务管理接口 ==========
    
    /**
     * 提交事务
     * @param hton handlerton指针
     * @param thd 线程句柄
     * @param all 是否提交全部事务层级
     * @return 0表示成功,非0表示失败
     */
    int (*commit)(handlerton *hton, THD *thd, bool all);
    
    /**
     * 回滚事务
     * @param hton handlerton指针
     * @param thd 线程句柄
     * @param all 是否回滚全部事务层级
     * @return 0表示成功,非0表示失败
     */
    int (*rollback)(handlerton *hton, THD *thd, bool all);
    
    /**
     * 准备两阶段提交
     * @param hton handlerton指针
     * @param thd 线程句柄
     * @param all 是否准备全部事务层级
     * @return 0表示成功,非0表示失败
     */
    int (*prepare)(handlerton *hton, THD *thd, bool all);
    
    /**
     * XA事务恢复
     * @param hton handlerton指针
     * @param list XA事务ID列表
     * @return 找到的XA事务数量
     */
    int (*recover)(handlerton *hton, XID *list, uint len);
    
    /**
     * 提交XA事务
     * @param hton handlerton指针
     * @param xid XA事务ID
     * @return 0表示成功,非0表示失败
     */
    int (*commit_by_xid)(handlerton *hton, XID *xid);
    
    /**
     * 回滚XA事务
     * @param hton handlerton指针
     * @param xid XA事务ID
     * @return 0表示成功,非0表示失败
     */
    int (*rollback_by_xid)(handlerton *hton, XID *xid);
    
    // ========== 保存点管理 ==========
    
    /**
     * 创建保存点
     * @param hton handlerton指针
     * @param thd 线程句柄
     * @param sv 保存点结构
     * @return 0表示成功,非0表示失败
     */
    int (*savepoint_set)(handlerton *hton, THD *thd, void *sv);
    
    /**
     * 回滚到保存点
     * @param hton handlerton指针
     * @param thd 线程句柄
     * @param sv 保存点结构
     * @return 0表示成功,非0表示失败
     */
    int (*savepoint_rollback)(handlerton *hton, THD *thd, void *sv);
    
    /**
     * 释放保存点
     * @param hton handlerton指针
     * @param thd 线程句柄
     * @param sv 保存点结构
     * @return 0表示成功,非0表示失败
     */
    int (*savepoint_release)(handlerton *hton, THD *thd, void *sv);
    
    /**
     * 保存点数据大小
     */
    uint savepoint_offset;
    
    // ========== 表管理接口 ==========
    
    /**
     * 发现表文件
     * @param hton handlerton指针
     * @param db 数据库名
     * @param name 表名
     * @param table_def 表定义(输出参数)
     * @return true表示找到,false表示未找到
     */
    bool (*discover_table)(handlerton *hton, THD *thd, 
                          const char *db, const char *name,
                          dd::Table **table_def);
                          
    /**
     * 发现表名列表
     * @param hton handlerton指针
     * @param db 数据库名  
     * @param dirp 目录句柄
     * @param result 结果列表
     * @return 0表示成功,非0表示失败
     */
    int (*discover_table_names)(handlerton *hton, const char *db,
                               MY_DIR *dirp,
                               handlerton::discovered_list *result);
                               
    /**
     * 删除表实现
     * @param hton handlerton指针
     * @param name 表名
     * @return 0表示成功,非0表示失败
     */
    int (*drop_table)(handlerton *hton, const char *name);
    
    /**
     * 重命名表实现
     * @param hton handlerton指针
     * @param from 原表名
     * @param to 新表名
     * @return 0表示成功,非0表示失败
     */
    int (*rename_table)(handlerton *hton, const char *from, const char *to);
    
    // ========== 统计信息接口 ==========
    
    /**
     * 获取表统计信息
     * @param hton handlerton指针
     * @param thd 线程句柄
     * @param check_opt 检查选项
     * @param name 表名
     * @return 统计信息结构
     */
    int (*get_tablespace_statistics)(handlerton *hton, const char *path,
                                   ha_tablespace_statistics *stats);
    
    /**
     * 更新表统计信息
     * @param hton handlerton指针
     * @param thd 线程句柄
     * @param table 表对象
     * @return 0表示成功,非0表示失败
     */
    int (*update_table_statistics)(handlerton *hton, THD *thd, TABLE *table);
    
    // ========== 系统变量和状态变量 ==========
    
    /**
     * 系统变量数组
     */
    struct st_mysql_sys_var **system_vars;
    
    /**
     * 状态变量数组
     */
    struct st_mysql_show_var *status_vars;
    
    /**
     * 获取系统变量值
     * @param thd 线程句柄
     * @param var 变量类型
     * @return 变量值
     */
    ulong (*get_sys_var_value)(THD *thd, int var);
    
    // ========== 复制支持接口 ==========
    
    /**
     * 准备复制
     * @param thd 线程句柄
     * @return 0表示成功,非0表示失败
     */
    int (*binlog_func)(handlerton *hton, THD *thd, enum_binlog_func fn, void *arg);
    
    /**
     * 检查是否支持复制
     * @return true表示支持,false表示不支持
     */
    bool (*is_supported_system_table)(const char *db, const char *table_name,
                                     bool is_sql_layer_system_table);
                                     
    // ========== 全文搜索接口 ==========
    
    /**
     * 创建全文索引解析器
     */
    int (*create_parser)(MYSQL_FTPARSER_PARAM *param);
    
    // ========== 分区支持 ==========
    
    /**
     * 分区标志位
     */
    uint32 partition_flags;
    
    /**
     * 获取分区处理器
     * @param table 表对象
     * @param mem_root 内存分配器
     * @return 分区处理器指针
     */
    Partition_handler *(*get_partition_handler)(TABLE *table, 
                                               MEM_ROOT *mem_root);
};

/**
 * handlerton功能标志位定义
 */
enum handlerton_flags {
    HTON_NO_FLAGS = 0,
    HTON_CLOSE_CURSORS_AT_COMMIT = (1 << 0),   ///< 提交时关闭游标
    HTON_ALTER_NOT_SUPPORTED = (1 << 1),       ///< 不支持ALTER TABLE
    HTON_CAN_RECREATE = (1 << 2),              ///< 可以重新创建
    HTON_FLUSH_AFTER_RENAME = (1 << 3),        ///< 重命名后需要刷新
    HTON_NOT_USER_SELECTABLE = (1 << 4),       ///< 用户不能选择此引擎
    HTON_TEMPORARY_NOT_SUPPORTED = (1 << 5),   ///< 不支持临时表
    HTON_SUPPORT_LOG_TABLES = (1 << 6),        ///< 支持日志表
    HTON_NO_PARTITION = (1 << 7),              ///< 不支持分区
    HTON_SUPPORTS_EXTENDED_KEYS = (1 << 8),    ///< 支持扩展键
    HTON_NATIVE_SYS_VERSIONING = (1 << 9),     ///< 支持系统版本控制
    HTON_SUPPORTS_ATOMIC_DDL = (1 << 10),      ///< 支持原子DDL
    HTON_SUPPORTS_FOREIGN_KEYS = (1 << 11),    ///< 支持外键
    HTON_SUPPORTS_TAGS = (1 << 12),            ///< 支持标签
    HTON_SUPPORTS_HISTOGRAM = (1 << 13)        ///< 支持直方图统计
};

4. 插件管理系统深度解析

4.1 插件管理器实现

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/**
 * 存储引擎插件管理器
 * 负责存储引擎的动态加载、注册和卸载
 */
class Storage_engine_plugin_manager {
private:
    // 全局存储引擎数组
    static handlerton *hton_table[MAX_HA];     ///< handlerton数组
    static uint total_ha;                      ///< 已注册的存储引擎数量
    
    // 插件注册表
    static std::unordered_map<std::string, handlerton*> engine_registry;
    static mysql_mutex_t plugin_mutex;         ///< 插件操作互斥锁
    
public:
    /**
     * 初始化插件管理器
     */
    static void init() {
        memset(hton_table, 0, sizeof(hton_table));
        total_ha = 0;
        mysql_mutex_init(key_LOCK_plugin, &plugin_mutex, MY_MUTEX_INIT_FAST);
    }
    
    /**
     * 注册存储引擎插件
     * @param engine_name 引擎名称
     * @param hton handlerton指针
     * @return 0表示成功,非0表示失败
     */
    static int register_storage_engine(const char *engine_name, handlerton *hton) {
        MUTEX_LOCK(lock, &plugin_mutex);
        
        // 检查是否已注册
        if (engine_registry.find(engine_name) != engine_registry.end()) {
            return ER_STORAGE_ENGINE_ALREADY_EXISTS;
        }
        
        // 检查数组容量
        if (total_ha >= MAX_HA) {
            return ER_TOO_MANY_STORAGE_ENGINES;
        }
        
        // 分配槽位
        uint slot = total_ha++;
        hton->slot = slot;
        hton_table[slot] = hton;
        
        // 加入注册表
        engine_registry[engine_name] = hton;
        
        // 调用引擎初始化
        if (hton->init && hton->init(hton)) {
            // 初始化失败,回滚注册
            unregister_storage_engine_internal(engine_name);
            return ER_STORAGE_ENGINE_INIT_FAILED;
        }
        
        LogErr(INFORMATION_LEVEL, ER_STORAGE_ENGINE_REGISTERED, engine_name);
        return 0;
    }
    
    /**
     * 卸载存储引擎插件
     * @param engine_name 引擎名称
     * @return 0表示成功,非0表示失败
     */
    static int unregister_storage_engine(const char *engine_name) {
        MUTEX_LOCK(lock, &plugin_mutex);
        
        auto it = engine_registry.find(engine_name);
        if (it == engine_registry.end()) {
            return ER_STORAGE_ENGINE_NOT_FOUND;
        }
        
        handlerton *hton = it->second;
        
        // 检查是否有表在使用此引擎
        if (count_tables_using_engine(hton) > 0) {
            return ER_STORAGE_ENGINE_IN_USE;
        }
        
        return unregister_storage_engine_internal(engine_name);
    }
    
    /**
     * 根据名称查找存储引擎
     * @param engine_name 引擎名称
     * @return handlerton指针,未找到返回nullptr
     */
    static handlerton* find_storage_engine(const char *engine_name) {
        MUTEX_LOCK(lock, &plugin_mutex);
        
        auto it = engine_registry.find(engine_name);
        return (it != engine_registry.end()) ? it->second : nullptr;
    }
    
    /**
     * 根据槽位获取存储引擎
     * @param slot 槽位编号
     * @return handlerton指针,槽位无效返回nullptr
     */
    static handlerton* get_storage_engine_by_slot(uint slot) {
        return (slot < total_ha) ? hton_table[slot] : nullptr;
    }
    
    /**
     * 获取所有已注册的存储引擎列表
     * @param engines 引擎列表(输出参数)
     * @return 引擎数量
     */
    static uint get_all_storage_engines(std::vector<handlerton*>& engines) {
        MUTEX_LOCK(lock, &plugin_mutex);
        
        engines.clear();
        engines.reserve(total_ha);
        
        for (uint i = 0; i < total_ha; ++i) {
            if (hton_table[i] != nullptr) {
                engines.push_back(hton_table[i]);
            }
        }
        
        return engines.size();
    }
    
    /**
     * 检查存储引擎是否可用
     * @param hton handlerton指针
     * @return true表示可用,false表示不可用
     */
    static bool is_storage_engine_available(handlerton *hton) {
        return hton && hton->state == SHOW_OPTION_YES;
    }
    
    /**
     * 清理插件管理器
     */
    static void cleanup() {
        MUTEX_LOCK(lock, &plugin_mutex);
        
        // 逆序清理所有引擎
        for (int i = total_ha - 1; i >= 0; --i) {
            handlerton *hton = hton_table[i];
            if (hton && hton->close) {
                hton->close(hton);
            }
        }
        
        engine_registry.clear();
        total_ha = 0;
        
        mysql_mutex_destroy(&plugin_mutex);
    }
    
private:
    /**
     * 内部卸载实现
     * @param engine_name 引擎名称
     * @return 0表示成功,非0表示失败
     */
    static int unregister_storage_engine_internal(const char *engine_name) {
        auto it = engine_registry.find(engine_name);
        if (it == engine_registry.end()) {
            return ER_STORAGE_ENGINE_NOT_FOUND;
        }
        
        handlerton *hton = it->second;
        uint slot = hton->slot;
        
        // 调用引擎清理
        if (hton->close) {
            hton->close(hton);
        }
        
        // 清理槽位
        hton_table[slot] = nullptr;
        
        // 如果是最后一个槽位,调整total_ha
        if (slot == total_ha - 1) {
            while (total_ha > 0 && hton_table[total_ha - 1] == nullptr) {
                total_ha--;
            }
        }
        
        // 从注册表移除
        engine_registry.erase(it);
        
        LogErr(INFORMATION_LEVEL, ER_STORAGE_ENGINE_UNREGISTERED, engine_name);
        return 0;
    }
    
    /**
     * 统计使用指定引擎的表数量
     * @param hton handlerton指针
     * @return 表数量
     */
    static uint count_tables_using_engine(handlerton *hton) {
        // 遍历所有打开的表,统计使用此引擎的数量
        uint count = 0;
        
        // 这里需要访问表缓存管理器
        // 具体实现略...
        
        return count;
    }
};

4.2 存储引擎实例创建流程

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
 * 存储引擎Handler实例创建和管理
 */
class Handler_factory {
public:
    /**
     * 创建Handler实例
     * @param hton handlerton指针
     * @param share 表共享信息
     * @param partitioned 是否为分区表
     * @param mem_root 内存分配器
     * @return Handler实例指针
     */
    static handler* create_handler(handlerton *hton, TABLE_SHARE *share,
                                  bool partitioned, MEM_ROOT *mem_root) {
        DBUG_TRACE;
        
        // 检查存储引擎是否可用
        if (!Storage_engine_plugin_manager::is_storage_engine_available(hton)) {
            LogErr(ERROR_LEVEL, ER_STORAGE_ENGINE_NOT_AVAILABLE, hton->name);
            return nullptr;
        }
        
        // 调用存储引擎的create函数
        handler *h = hton->create(hton, share, partitioned, mem_root);
        if (h == nullptr) {
            LogErr(ERROR_LEVEL, ER_HANDLER_CREATE_FAILED, hton->name);
            return nullptr;
        }
        
        // 设置表对象引用
        h->table_share = share;
        h->ht = hton;
        
        // 初始化性能监控接口
        if (PSI_TABLE_CALL(get_table_share) != nullptr) {
            h->m_psi = PSI_TABLE_CALL(get_table_share)(false, share);
        }
        
        // 初始化引用长度
        h->ref_length = h->get_ref_length();
        
        LogDebug(STORAGE_ENGINE_LOG, "Created handler for table %s.%s using engine %s",
                share->db.str, share->table_name.str, hton->name);
                
        return h;
    }
    
    /**
     * 销毁Handler实例
     * @param handler Handler实例指针
     */
    static void destroy_handler(handler *handler) {
        if (handler == nullptr) return;
        
        handlerton *hton = handler->ht;
        const char *engine_name = hton->name;
        const char *table_name = handler->table_share ? 
                                handler->table_share->table_name.str : "unknown";
        
        LogDebug(STORAGE_ENGINE_LOG, "Destroying handler for table %s using engine %s",
                table_name, engine_name);
        
        // 调用存储引擎的destroy函数
        if (hton->destroy) {
            hton->destroy(handler);
        } else {
            // 默认实现:直接删除
            delete handler;
        }
    }
    
    /**
     * 根据表类型创建Handler
     * @param table_type 表类型名称
     * @param share 表共享信息
     * @param mem_root 内存分配器
     * @return Handler实例指针
     */
    static handler* create_handler_by_name(const char *table_type,
                                          TABLE_SHARE *share, 
                                          MEM_ROOT *mem_root) {
        handlerton *hton = Storage_engine_plugin_manager::find_storage_engine(table_type);
        if (hton == nullptr) {
            LogErr(ERROR_LEVEL, ER_UNKNOWN_STORAGE_ENGINE, table_type);
            return nullptr;
        }
        
        return create_handler(hton, share, false, mem_root);
    }
    
    /**
     * 为分区表创建Handler
     * @param hton handlerton指针
     * @param share 表共享信息
     * @param mem_root 内存分配器
     * @return Handler实例指针
     */
    static handler* create_partition_handler(handlerton *hton, 
                                           TABLE_SHARE *share,
                                           MEM_ROOT *mem_root) {
        // 检查是否支持分区
        if (hton->flags & HTON_NO_PARTITION) {
            LogErr(ERROR_LEVEL, ER_PARTITION_NOT_SUPPORTED, hton->name);
            return nullptr;
        }
        
        return create_handler(hton, share, true, mem_root);
    }
    
private:
    /**
     * 获取引用长度的默认实现
     */
    static uint get_default_ref_length() {
        return sizeof(my_off_t);  // 默认使用文件偏移量大小
    }
};

5. 存储引擎生命周期管理

5.1 存储引擎初始化流程时序图

sequenceDiagram participant Server as MySQL服务器 participant PluginMgr as 插件管理器 participant Engine as 存储引擎 participant Handler as Handler实例 participant Table as 表对象 Note over Server,Table: 存储引擎生命周期管理流程 Server->>PluginMgr: 1. 服务器启动,加载插件 PluginMgr->>PluginMgr: 2. 扫描插件目录 PluginMgr->>Engine: 3. 动态加载引擎.so文件 Engine->>PluginMgr: 4. 注册handlerton结构 Note over PluginMgr: 存储引擎注册阶段 PluginMgr->>PluginMgr: 5. 分配引擎槽位 PluginMgr->>Engine: 6. 调用init()初始化 Engine->>Engine: 7. 初始化全局资源 Engine->>Engine: 8. 注册系统变量 Engine->>PluginMgr: 9. 初始化完成 Note over Server: 表操作阶段 Server->>PluginMgr: 10. 请求创建Handler PluginMgr->>Engine: 11. 调用create()创建Handler Engine->>Handler: 12. 分配Handler实例 Handler->>Handler: 13. 初始化Handler状态 Engine->>PluginMgr: 14. 返回Handler指针 Note over Handler: Handler使用阶段 Server->>Handler: 15. open()打开表 Handler->>Table: 16. 打开底层表文件 Table->>Handler: 17. 返回文件句柄 loop SQL操作循环 Server->>Handler: 18. 调用数据操作接口 Handler->>Table: 19. 执行底层存储操作 Table->>Handler: 20. 返回操作结果 Handler->>Server: 21. 返回标准化结果 end Note over Handler: 清理阶段 Server->>Handler: 22. close()关闭表 Handler->>Table: 23. 关闭底层文件 Server->>PluginMgr: 24. 销毁Handler实例 PluginMgr->>Engine: 25. 调用destroy() Engine->>Handler: 26. 释放Handler资源 Note over Server: 服务器关闭阶段 Server->>PluginMgr: 27. 服务器关闭 PluginMgr->>Engine: 28. 调用close()清理 Engine->>Engine: 29. 释放全局资源 Engine->>PluginMgr: 30. 清理完成 PluginMgr->>PluginMgr: 31. 卸载插件

5.2 表打开和关闭流程

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/**
 * 表操作生命周期管理
 * 管理表的打开、使用和关闭过程
 */
class Table_lifecycle_manager {
public:
    /**
     * 打开表的完整流程
     * @param thd 线程句柄
     * @param table_share 表共享信息
     * @param table 表对象
     * @return 0表示成功,非0表示失败
     */
    static int open_table(THD *thd, TABLE_SHARE *share, TABLE *table) {
        DBUG_TRACE;
        int error = 0;
        
        // 1. 创建Handler实例
        handler *h = Handler_factory::create_handler(share->db_type(), 
                                                    share, false, 
                                                    &table->mem_root);
        if (h == nullptr) {
            return ER_OUTOFMEMORY;
        }
        
        table->file = h;
        h->table = table;
        
        // 2. 设置表标志和选项
        h->table_flags_are_set = false;
        
        // 3. 调用Handler的open方法
        char path[FN_REFLEN + 1];
        build_table_filename(path, sizeof(path) - 1,
                           share->db.str, share->table_name.str, "", 0);
                           
        error = h->open(path, table->db_stat, HA_OPEN_IGNORE_IF_LOCKED);
        if (error) {
            LogErr(ERROR_LEVEL, ER_CANT_OPEN_FILE, path, error);
            goto err;
        }
        
        // 4. 初始化索引信息
        error = init_table_indexes(table);
        if (error) goto err;
        
        // 5. 设置主键和唯一键信息
        error = setup_key_info(table);
        if (error) goto err;
        
        // 6. 初始化字段默认值
        error = init_field_defaults(table);
        if (error) goto err;
        
        // 7. 获取表统计信息
        error = h->info(HA_STATUS_VARIABLE | HA_STATUS_CONST);
        if (error) goto err;
        
        // 8. 设置记录缓冲区
        if (!(table->record[0] = (uchar*)alloc_root(&table->mem_root, 
                                                   share->reclength))) {
            error = ER_OUTOFMEMORY;
            goto err;
        }
        
        if (!(table->record[1] = (uchar*)alloc_root(&table->mem_root, 
                                                   share->reclength))) {
            error = ER_OUTOFMEMORY;
            goto err;
        }
        
        // 9. 初始化字段指针
        error = init_field_pointers(table);
        if (error) goto err;
        
        LogDebug(TABLE_LOG, "Successfully opened table %s.%s using engine %s",
                share->db.str, share->table_name.str, h->table_type());
                
        return 0;
        
    err:
        if (table->file) {
            table->file->close();
            Handler_factory::destroy_handler(table->file);
            table->file = nullptr;
        }
        return error;
    }
    
    /**
     * 关闭表的完整流程
     * @param table 表对象
     */
    static void close_table(TABLE *table) {
        DBUG_TRACE;
        
        if (table->file == nullptr) return;
        
        const char *table_name = table->s ? table->s->table_name.str : "unknown";
        const char *engine_name = table->file->table_type();
        
        LogDebug(TABLE_LOG, "Closing table %s using engine %s",
                table_name, engine_name);
        
        // 1. 刷新未提交的更改
        if (table->file->has_transactions()) {
            table->file->external_lock(current_thd, F_UNLCK);
        }
        
        // 2. 关闭Handler
        table->file->close();
        
        // 3. 清理Handler实例
        Handler_factory::destroy_handler(table->file);
        table->file = nullptr;
        
        // 4. 清理表级资源
        cleanup_table_resources(table);
        
        LogDebug(TABLE_LOG, "Table %s closed successfully", table_name);
    }
    
private:
    /**
     * 初始化表索引信息
     */
    static int init_table_indexes(TABLE *table) {
        TABLE_SHARE *share = table->s;
        handler *file = table->file;
        
        // 设置主键信息
        if (share->primary_key < MAX_KEY) {
            table->key_info = &share->key_info[share->primary_key];
        }
        
        // 检查索引功能支持
        for (uint i = 0; i < share->keys; i++) {
            KEY *key = &share->key_info[i];
            ulong flags = file->index_flags(i, 0, true);
            
            // 检查是否支持部分键扫描
            if (!(flags & HA_READ_NEXT)) {
                key->flags |= HA_NOSAME;  // 标记为不支持范围扫描
            }
            
            // 检查是否支持NULL值
            if (!(flags & HA_NULL_IN_KEY)) {
                for (uint j = 0; j < key->user_defined_key_parts; j++) {
                    if (key->key_part[j].field->null_bit) {
                        return ER_WRONG_INDEX_DEFINITION;
                    }
                }
            }
        }
        
        return 0;
    }
    
    /**
     * 设置键信息
     */
    static int setup_key_info(TABLE *table) {
        TABLE_SHARE *share = table->s;
        
        // 查找最优的主键或唯一键
        table->primary_key = share->primary_key;
        
        if (table->primary_key >= MAX_KEY) {
            // 没有显式主键,寻找唯一非空键
            for (uint i = 0; i < share->keys; i++) {
                KEY *key = &share->key_info[i];
                if ((key->flags & HA_NOSAME) && !(key->flags & HA_NULL_PART_KEY)) {
                    table->primary_key = i;
                    break;
                }
            }
        }
        
        return 0;
    }
    
    /**
     * 初始化字段默认值
     */
    static int init_field_defaults(TABLE *table) {
        for (Field **field = table->field; *field; field++) {
            if ((*field)->has_insert_default_general_value_expression() ||
                (*field)->has_update_default_general_value_expression()) {
                // 设置默认值表达式
                continue;
            }
            
            // 设置简单默认值
            (*field)->set_default();
        }
        
        return 0;
    }
    
    /**
     * 初始化字段指针
     */
    static int init_field_pointers(TABLE *table) {
        TABLE_SHARE *share = table->s;
        uchar *record = table->record[0];
        
        for (uint i = 0; i < share->fields; i++) {
            Field *field = share->field[i];
            field->ptr = record + field->offset(record);
            
            if (field->null_bit) {
                field->null_ptr = record + field->null_offset();
            }
        }
        
        return 0;
    }
    
    /**
     * 清理表级资源
     */
    static void cleanup_table_resources(TABLE *table) {
        // 清理字段资源
        if (table->field) {
            for (Field **field = table->field; *field; field++) {
                (*field)->cleanup();
            }
        }
        
        // 清理键缓存
        if (table->key_info) {
            // 键信息由TABLE_SHARE管理,无需单独释放
        }
        
        // 重置表状态
        table->db_stat = 0;
        table->status = STATUS_NO_RECORD;
    }
};

6. 总结与展望

6.1 接口层核心优势

MySQL存储引擎接口层设计具有以下优势:

  • 统一抽象:为所有存储引擎提供统一的操作接口
  • 插件化架构:支持动态加载和卸载存储引擎
  • 透明性:上层SQL无需关心底层存储实现
  • 扩展性:易于开发和集成新的存储引擎

6.2 设计模式应用

接口层广泛应用了多种设计模式:

  1. 抽象工厂模式:Handler类作为产品接口,各存储引擎作为具体工厂
  2. 策略模式:不同存储引擎实现不同的数据存储策略
  3. 模板方法模式:定义通用的表操作流程模板
  4. 适配器模式:将不同存储引擎适配为统一接口

6.3 未来发展方向

  1. 云原生支持:更好地支持云存储和分布式文件系统
  2. 性能优化:针对新硬件的接口优化,如NVMe、持久化内存
  3. 智能化管理:自动选择最优存储引擎和参数配置
  4. 标准化接口:与行业标准存储接口的更好集成

通过深入理解MySQL存储引擎接口层的设计和实现,我们能够更好地选择和优化存储引擎,并在需要时开发定制的存储解决方案。

本文由 tommie blog 原创发布