在 MySQL 中,写入一条数据的流程可以概括为以下几个步骤:
1. 客户端提交请求
客户端通过 MySQL 的连接协议向服务器发送一条INSERT
、UPDATE
或DELETE
等写操作的 SQL 语句。
2. 链接器
- 连接管理:MySQL Server使用线程池来处理并发连接。在MySQL 8.0中,线程池得到了显著优化,可以更好地处理大量并发连接。
- 身份验证:MySQL 8.0引入了新的默认认证插件
caching_sha2_password
,提供了更强的安全性。此外,支持多种身份验证方法,包括PAM、LDAP等。
3. 语法解析与优化
- 解析器:将SQL语句解析成内部的数据结构,并进行语法检查。
- 预处理器:进一步检查语句是否合法,例如表是否存在,字段类型是否匹配等。
- 查询优化器:
- MySQL 8.0对查询优化器进行了多项改进,比如更好的索引选择、更智能的成本估算模型。
- 对于INSERT语句,虽然相对简单,但优化器仍然会考虑是否有可用的索引来加速后续可能的查找操作。
4. 执行器
执行器根据生成的执行计划执行写入操作:
- 判断目标表是否存在。
- 根据表的结构和索引信息定位需要写入的行。
5. 引擎层处理
MySQL 通过存储引擎完成数据写入,以下以 InnoDB 引擎为例:
- 生成日志:
- 写入操作首先会生成redo log(重做日志) 和undo log(回滚日志)。
- Redo Log:用于保障宕机恢复。
- Undo Log:用于支持事务的回滚和 MVCC(多版本并发控制)。
- 修改内存中的数据页:
- MySQL 会先将数据写入到Buffer Pool(内存中的缓存区域)。
- 通过
change buffer
优化非唯一索引的写操作。
- 标记脏页:
- 修改的数据页会被标记为脏页,定期通过刷脏(flush)操作写入磁盘。
6. 提交事务
如果使用了事务(例如BEGIN...COMMIT
),事务提交时会完成以下步骤:
- 将Redo Log 的状态标记为提交(Commit)。
- 将数据从Buffer Pool 刷新到磁盘文件(如
.ibd
文件)。
如果未开启事务控制(autocommit=1
),每条写入语句都会自动提交。
7. Binlog 写入
- MySQL 会将操作记录写入Binlog(归档日志)。
- Binlog 的作用:
- 数据备份和恢复。
- 主从复制。
8. 客户端确认
MySQL 将写入操作的执行结果返回给客户端,至此一次写入流程完成。
写入优化点
- 合理设计索引:减少索引维护的开销。
- 使用批量插入:减少事务提交的频率。
- 调优参数:如
innodb_log_buffer_size
和innodb_buffer_pool_size
。 - 异步刷盘:优化
innodb_flush_log_at_trx_commit
参数。