Mysql 基础知识二
文章目录
一、基础知识
- 表存储引擎必须用InnoDB
- 字符集必须使用utf8mb4 (utf8不是真utf8)
- 禁止使用存储过程、视图、触发器、Event
- 命名规则:库、表、字段列都必须小写,用 _ 分隔
- 表必须有主键,默认推荐使用unsignd整形,命名为id,自增
- 字段必须为not null,原则上每个字段必须有默认值
- 合理建立索引
- 三范式与反范式(业务出发,权衡利弊、适当冗余)
- 分库分表:垂直拆分(分库)、水平拆分(分表) 分表:垂直分割(一表变多表,结构相同)、水平分割(大表拆小表)
- 数据库集群:主从架构
二、事务、锁、索引,数据库性能的死亡三角
A. 事务
- 事务特性ACID:原子性、一致性、隔离性、持久性
- 事务的隔离级别:
- Read uncommited(未提交读),无法保证;级别最低,一般不用
- Read commited(可提交读),可避免脏读;不加锁
- Repeatable read(可重复读),可避免脏读、不可重复读;Mysql默认级别,对数据加锁
- Serializable(串行化),可避免脏读、不可重复读、幻读;会锁表,慎用
B. 锁
C. 索引
- 索引类型:
- 普通索引:加快数据检索
- 唯一索引:避免重复
- 主键索引:效率最高
- 全文索引:一般不用,通过第三方工具来实现(ES、Sphinx等)
- 索引的好处:提高检索效率,减少检索数据量、降低IO成本
- 索引的弊端:增加增删改的操作IO、占用较大的存储空间
- 什么时候该用索引?
- 频繁作为条件查询的字段
- 唯一性太差的字段不适宜单独索引,数据的区分度过低
- 索引字段类型:字符串字段查询时一定要加引号,否则索引失效引发全表扫描
- 索引优化:善用explain分析索引有效性
三、数据库主从不一致,如何破
- 数据库集群:一主多从,主从复制,读写分离【主库负责写,主库和从库都负责读】
- 目的:降低主库压力,提升读效率
- 问题产生:主从同步存在延时
- 写请求->读请求(主从同步未完成,读到不一致的脏数据)->主从同步完成
解决方案:
- 忽略(业务能够接受,架构越简单越好)
- 强制读主(增加主库压力、配合缓存减少压力,无法发挥集群效果)
- 选择性读主(有写操作的后续读请求都读主库,简单粗暴相对有效)
- 选择性读主(缓存db:table:PK,缓存过期时间设为主从延时,缓存里有这个key就读主库,否则读从库,实现复杂性较高)
- 选择性读主(对数据实时要求高,如资金操作,强制读主)
业务需求决定技术方案:尽量不要让构架设计过于复杂
四、数据库层面的挑战主要在哪
- 连接数过多
- 慢查询、全表扫描
- 事务、锁
- 数据量合理预估和分布
- 查询数过多(合并查询)
- 并发更新(异步化、串行化、最小粒度)
- ……
高并发下很多看似不会出问题的操作最终都出了问题
五、数据库性能优化有哪些手段
A、数据库层面
- 合理设计表结构和表字段
- 合理预估数据量,做好分库分表设计
- 合理建立索引
- 适当冗余数据,减少关联查询
- 使用主从集群,减轻主库压力,提升查询效率
B. 代码层面
- 合理使用事务
- 合理使用锁
- 合并请求,减少数据库的操作次数(批量查询、批量更新)
C. 架构层面
- 使用前端缓存,减少查询
- 使用消息队列,减少并发
D. 问题追踪
- 慢查询日志
- 死锁监测
六、以上优化都做了,还有哪些坑
- 分库带来分布式事务如何解决?
- 分库分表后,原来很简单的聚合、排序、联表查询都不可用了
- 非分表字段如何做查询?
- 为什么会出现死锁
- ……
高并发,大数据是数据库最大的挑战,优化没有尽头
没有解决一切问题的架构,只有结合业务,适当妥协的方案
七、一些坑和注意点
- insert ignore:会导致自增 ID不连续,跳跃式增长
- select * :如果没有缓存一定要指定要查询的字段
- order by rand():慎用,数据量大的表禁用
- in和exists:外表大用in,内表大用exists
- null值查询:field is null才能查到
- varchar字段要设置合适的长度
八、数据库不仅仅是MySQL
- Redis:NoSQL键值数据库
- MogoDB:NoSQL文档数据库
- TiDB:分布式NewSQL关系数据库
- 其它
根据业务场景选用合适的存储方案