MySQL

分库分表
- 分库:数据库扩展到多个物理节点。
- 分表:表分块保存到不同数据库中。
- Mycat: bin中的dataMigrate脚本执行扩容/缩容过程。

事务隔离级别
- 未提交读:出现脏读。
- 已提交读:不可重复读。
- 可重复读:幻读。
- 串行化。
索引
- B+树:IO次数少,查询性能稳定,范围查询更简便。
- Hash:等值查询。
- SQL优化:
- 慢日志查询,explain分析
- type为index或all。
- extra为文件排序或者临时表,需要优化。
- 合理安排联合索引的顺序;
- 最左匹配原则;
- 最左前缀原则。
- 慢日志查询,explain分析
- 聚集索引:索引的逻辑顺序与存储的物理顺序相同。
- 非聚集索引:回表问题,覆盖索引解决。
- 密集索引:密集索引的每个搜索码都对应一个索引值。
- 稀疏索引:部分索引码建立索引项。
- 唯一索引:第一个满足就返回。
- 普通索引:满足一直查询,直到不满足。
- 索引维护:更新索引统级信息,删除索引碎片。
- 页:Innodb存储的基本结构。头部数据保存两个指针分别指向上下页,主体数据关注数据和索引的存储。
- 索引的更新:
| 唯一索引 | 普通索引 | |
|---|---|---|
| 记录要更新的页在内存中 | 没有冲突则插入值 | 插入值 |
| 记录要更新的目标页不在内存中 | 读取到内存中,没有冲突则插入值 | 将更新记录在change buffer(节省随机读磁盘的IO消耗)中 |
- 没有使用索引的情况下InnoDB会使用表级锁。
- 相关操作:
- 同一个表最多创建16条。
- 创建:create 索引名称 on 表名(字段)
- 查看索引:show index from 表名
- 适合建立索引的字段:
- 表的主键,外键
- 数据量超过300
- 用于连接的字段
- where子句中的字段
- 不走索引的情况:
- 索引列存在函数运算
- 索引列存在隐式转换
- 模糊查询%
- or条件中存在字段没有索引
- 优化器弃用索引扫描,使用全表扫描。
- “空洞”问题
- 删除行时,行标记为“已删除”,没有物理删除,空间没有释放。
- InnoDB的Purge线程会异步清理没用的索引和行,但不释放空间导致形成“空洞”。
- “空间”长度不足不能用来存新的行。
- 清理空洞:MyISAM使用optimize table命令;InnoDB通过转换数据引擎,重写数据。
MVCC
-
解决了RC隔离级别和RR隔离级别下读同一行和写同一行两个事务的并发问题。
-
隐藏列:行ID,事务ID,回滚指针。回滚指针指向行ID。
-
undo log存放版本链(回滚指针指向行ID)。
-
read view(可见性判断):通过回滚指针指向的行ID,取出事务ID,比较事务ID,保证获取的版本是当前最稳定的版本。
-
RC隔离级别下每次读取生成read view;RR隔离级别下只有第一次读取生成read view,之后都是复用第一次的read view。
锁
- 全局锁:全局逻辑备份。
- 表锁:读锁不互斥,写锁互斥。
- 行锁:两阶段锁协议,所有事务分两阶段对事务进行加锁和解锁。
- gap锁(间隙锁):防止同一事务的两次当前读出现幻读。除了唯一索引的唯一搜索外都会获取gap锁或next-key锁(行锁+间隙锁)。
- 读写锁。
- 死锁(两种解决办法):超时检测:等待直到超时;死锁检测:发现死锁主动回滚某个事务。
- 热点行:死锁消耗CPU,可临时关闭。控制并发度。分治。
- Innodb如何加锁:Record lock:对索引项加锁。Gap lock:对索引项之间的间隙加锁;Next-Key锁:前两种的组合。
log
- undo log:回滚行记录到某个版本。
- redo log:记录数据页的物理修改,恢复提交后的物理数据页。
- bin log:记录数据库增删改,用于数据恢复。
- MySQL日志两段式提交:先更新redo log,redo log设置为prepare状态;再更新bin log,redo log设置为commit。目的是两份日志同步。
MySql主从同步
-
数据库主从同步延迟:主数据库负责数据的写,更新到从数据库;多个从数据库负责数据的读取。
-
主库发送bin log;从库接收bin log,写relay log。
-
异步复制,半同步复制(反馈给主库后告知当前session操作完成)。
范式
- 1NF:原子性约束,每个属性不可再分
- 2NF:唯一性约束,非主属性完全依赖主属性
- 3NF:冗余性约束,非主属性对主属性不存在传递函数依赖
MySql优化
-
存储引擎
-
缓存
Hibernate的缓存机制:
一级缓存(Session级别):只能当前事务访问,内置的不能卸载。
二级缓存(SessionFactory级别):被所有事务共享访问,可选的。不支持分布式缓存,可使用redis代替。
-
索引
-
分库分表
-
主从复制,读写分离
-
备份
MyBatis的实现原理
- mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件(也可以用Java文件配置的方式,需要添加@Configuration)来构建SqlSessionFactory(SqlSessionFactory是线程安全的)。
- SqlSessionFactory的实例直接开启一个SqlSession。
- 通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交。
- 关闭SqlSession。
Hibernate的实现原理
- 利用反射原理,将实体类中的字段按照xml配置或者annotation解析成一条或者多条sql语句,然后放入数据库执行。
InnoDB如何实现事务

事务特性,怎么保证
- 原子性:undo log
- 一致性:其他三种特性保证
- 隔离性:锁和MVCC
- 持久性:redo log
多线程连接数据库
- 在多线程环境下,Connection不是线程安全的。
- 数据库连接池中:非事务场景下线程依次调用方法可能使用不同的Connection实例;事务场景下,transaction只会使用此Connection。
你知道的越多,你不知道的越多。

一个开放源码的小型关联式数据库管理系统。
浙公网安备 33010602011771号