一条查询语句执行过程
首先由连接器处理客户端的连接,然后分析器分析sql词法和语法是否有问题,接下来是优化器,针对sql中涉及的索引做优化处理,最后由执行器先判断用户是有具有查询权限,然后操作存储引擎执行sql语句。
一条更新语句执行过程
更新SQL过程和查询过程前部分类似,只是到了执行sql阶段,需要操作两个日志,一个是redo日志,一个是binlog日志,更新的结果,innoDB存储引擎会先把结果写入到redo日志中,并进入prepare阶段,然后mysql把变动的sql写入到binlog中,最后innoDB再commit,完成数据写日志。
两种日志的区别和联系
-
redo日志:
- redo日志是innoDB存储引擎自己实现的机制,不是mysql实现的机制
- redo日志的记录是循环写入的,即写完最后一个文件,会从头再写入第一个文件里
- redo日志是物理日志,记录的是"在某个数据页上做了什么修改"
-
binlog
- binlog是MySQL的Server层实现的,所有引擎都可以使用
- binlog是追加写入文件的,不会覆盖之前文件
- binlog是逻辑日志,记录的是这个语句的原始逻辑,比如"给id为1的字段a加2"
事务隔离性的实现
todo: https://www.jianshu.com/p/398d788e1083
长事务如何避免
-
从客户端角度看
- 确认是否使用了set autocommit=0。可以开启mysql的general_log来查看。
- 确认是否有不必要的只读事务
- 业务代码连接数据库时,根据自身业务情况,通过SET MAX_EXECCUTION_TIME命令,来控制每个语句执行的最长时间,避免单个语句意外执行太长时间。
-
从服务端的角度看
- 监控 information_schema.Innodb_trx表,设置长事务阈值,超过就报警/或者kill
- Percona的pt-kill这个工具不错,推荐使用(todo 研究下这是个啥)
- 在业务功能测试阶段要求输出所有的general_log,分析日志行为提前发现问题
- 如果使用的是MySQL5.6或者更新版本,把innodb_undo_tablespaces设置成2(或者更大值)。如果真的出现大事务导致回滚段过大,这样设置后清理起来更方便。
索引相关概念定义
聚簇索引(这块叫法有点乱,待确定)
mysql默认会给主键创建索引,即主键索引,又叫聚簇索引,主键索引叶子节点存储的是整条数据,当表没有主键时,mysql会创建一个rowID做主键。
非聚簇索引
非聚簇索引的叶子结点的内容是主键的值。在innodb里,非聚簇索引也叫二级索引。
回表
查询数据过程中,回到主键索引树搜索的过程,叫做回表。
覆盖索引
普通索引上的数据可以覆盖我们原本要查询的数据,不用回表去查询数据,这种索引叫做覆盖索引。
联合索引的设计
- 第一原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。
- 空间占用考虑:如(name,age)字段,比较适合创建(name,age)联合索引,和age单字段索引
- 索引下推:例如需要查询"名字第一个字是张,年龄为10的所有男孩",在mysql5.6之前,只能从符合名称条件的数据,一条一条回表查出数据行,再对比字段值,而mysql5.6引入的索引下推优化,可以在索引遍历过程中,对索引中包含的字段做判断,直接过滤掉不满足条件的记录,减少回表次数。