关于Mysql(5.6)的一些思考
2019-08-05 本文已影响2人
A_You
事物级别
- MySQL 默认事物级别是可重复读;Oracle默认为读已提交
>> SELECT @@global.tx_isolation;
>> REPEATABLE-READ
- 事务级别的优先级:
1:读未提交
直接返回记录行上的最新记录;没有视图的概念
2:读已提交
视图是在每个sql语句开始时创建的。
3:可重复读
事物开启会建立视图,依据视图做到事务隔离
4:串行化
读写均加锁来实现
5:事务隔离的实现-可重复度级别
回滚日志.png
实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。建议尽量不要写长事物。
6:查找时间超过 60s的事物
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>=60;
7: 没有特殊逻辑;尽量不要对Read进行事务管理
性能测试如下:https://www.percona.com/blog/2019/07/15/mysql-the-impact-of-transactions-on-query-throughput/
一条查询SQL的执行计划
逻辑架构图.pngMysql大致可以分为Server层和存储引擎层
1:连接器
负责跟客户端建立连接、获取权限、维持和管理连接:
例如如下:
mysql -h$ip -P$port -u$user -p
mysql> show processlist;
+-----+-------------+---------------------------------------------+-------------+---------+--------+-----------------------------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+-------------+---------------------------------------------+-------------+---------+--------+-----------------------------------------------------------------------------+------------------+
| 1 | system user | | NULL | Connect | 173583 | Waiting for master to send event | NULL |
| 2 | system user | | NULL | Connect | -1 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL |
| 63 | demo | bjwfj-67p109-mediaforce-42.bfdabc.com:61820 | bfd_mf_data | Sleep | 16 | | NULL |
| 118 | root | localhost | NULL | Query | 0 | init | show processlist |
+-----+-------------+---------------------------------------------+-------------+---------+--------+-----------------------------------------------------------------------------+------------------+
对 druid中链接数进行查看如下:
当前连接池中的数目:1
这里涉及到一个问题,如果客户端太长时间没动静,连接器会自动断开,这个参数是由参数:wait_timeout控制,默认是 8 小时。目前业务端是基于连接池的,本省就是就可以控制connection的活跃数目;所以可将该值调整为 24小时。避免 Lost Connection to Mysql server during query 的异常;当然这里也存在问题;如果客户端Connection异常关闭,那么Mysql 端的连接也去就无法释放;所以有更加优雅的方式:
1: 定期断开长连接
2: Mysql 5.7+ 支持 mysql_reset_connection 来重新初始化链接
2:查询缓存
缓存的 key就是查询语句,Value就是缓存的行记录。但是大多数情况下不建议使用查询缓存,因为查询缓存往往弊大于利。缓存失效非常频繁,只要对一个表的更新,这表上所有的查询缓存都会清空。Mysql提供啦一种按需使用的方式,可以将 query_cache_type设置为DEMAND,这样默认的查询语句都不会使用缓存;可以显示指定SQL_CACHE 参数:
mysql> select SQL_CACHE * from T where ID=10;
Mysql8.0 已彻底将该功能移除并废弃掉
3:分析器
分析器做的就是词法分析,检验sql语句的合法性
4:优化器
优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。
5:执行器
MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。经常看到的rows_examined 就是执行中的指标。
一条更新Sql的执行计划
1:redo log
redo log.png
redo log 是innoDB引擎特有的日志。redo log其实就是Mysql中经常提到的WAL(Write-Ahead Logging)技术;关键点就是先写日志,在写磁盘,这样就大大降低啦磁盘的IO成本、查找成本。
2: binlog
binlog(归档日志)服务于server层,是逻辑日志,记录的是该语句的原始逻辑,同时是可以追加写;达到一定文件大小后会切换到下一个。
3:update 执行流程图
update流程图.png
这个就涉及到Mysql的两阶段提交事务
索引
1: 覆盖索引
目的是优化索引查询; 减少回表次数
eg:
select id from t where index_age between 2 and 5; # 查询的Id已经在索引index_age树上,不需要回表
同时假如你的业务有大量的类似于:依据 身份证号查找姓名;其实可以 为 身份证号 + 姓名为联合索引;极大的减少回表需求
2: 最左前缀原则
最左前缀原则的实现是依据 B+树索引来实现的
(name,age)索引示意图.jpg
3: 索引下推
而 MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数;