MySQL分为:
- Server层
1.1 连接器:跟客户端建立连接、获取权限、维持和管理连接。
mysql -hport -u$user -p:用户名密码不正确->“Access denied for user”;用户名密码正确->连接器到权限表里面查出拥有的权限。
连接成功后没有继续动作,连接处于空闲状态,show processlist命令结果Command列为“Sleep”。
客户端长时间没动静,连接器自动断开,由参数wait_timeout设置,默认8小时。
长连接、短连接:尽量使用长连接,但MySQL占用内存可能会太大,被系统强行杀掉(MySQL异常重启)
解决方法:1. 定期断开长连接;2. 版本5.7以上,在每执行一个较大的操作后,执行mysql_reset_connection重新初始化连接资源(不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完的状态)。
1.2 查询缓存:对于更新压力大的数据库来说,查询缓存的命中率低,不建议使用,参数query_cache_type设置为DEMAND,使用查询缓存可以用SQL_CACHE显式指定(select SQL_CACHE * from T where id = 100);MySQL8.0以后没有这个功能。
1.3 分析器:词法分析、语法分析
1.4 优化器:选择最佳索引;一个语句有多表关联(join)时,决定各表的连接顺序。
1.5 执行器:无索引执行流程:1. 调用InnoDB引擎取该表第一行,判断id值,如果是存在结果集,如果不是则跳过;2. 取下一行,重复1;3. 执行器将结果集返回给客户端。
rows_examined:表示语句执行过程中扫描了多少行,引擎扫描行数跟rows_examined不是完全相同的。 - 存储引擎层
日志:
- redo log:是InnoDB引擎特有的;物理日志,“在某个数据页上做了什么修改”;循环写,空间大小固定。
- binlog:MySQL的Server层实现的;逻辑日志,“记录了语句原始逻辑(sql语句)”;追加写,写到一定大小切换到下一个。
事务:
在MySQL中,事务支持是在引擎层实现的,MylSAM不支持,InnoDB支持。
事务具备的4个特征:原子性A、一致性C、隔离性I、持久性D
当数据库上多个事务同时执行的时候,可能出现脏读、不可重复读、幻读,->“隔离级别”
隔离级别:1. 读未提交 2. 读提交 3. 可重复读 4. 串行化
尽量避免长事务:每条记录更新时都会同时记录一条回滚操作,长事务意味着系统里面会存在很老的事务视图,所以回滚记录都必须保留,导致占用大量空间;占用锁资源。
索引:
常见模型:1. 哈希表:适用于等值查询的场景(值不是递增的,无序)
2. 有序数组:等值查询和范围查询性能都可,只适用静态存储(插入成本高)
3. 搜索树:N叉树
覆盖索引、前缀索引、索引下推
锁:
- 全局锁:对整个数据库实例加锁;使用场景:做全库逻辑备份
- 表级锁:表锁、MDL
- 行锁:
普通索引和唯一索引如何选择?
字符串创建索引的方式:
- 直接创建完整索引,可能占空间
- 创建前缀索引,节省空间,但会增加查询扫描次数,不能使用覆盖索引
- 倒序存储,再创建前缀索引,绕过字符串本身前缀的区分度不够问题,不支持范围查询
- 创建hash字段索引,查询性能稳定,有额外的存储和计算消耗,不支持范围查询
对索引字段做函数操作,可能会破坏索引值的有序性,索引失效;
- 直接在索引字段上做函数操作
- 隐式类型转换
- 隐式字符编码转换