Mysql知识点总结
本片文章只记录mysql相关概念,不做细节探究。参考javaGuide
存储引擎,show engines;
- InnoDB:支持事务,默认行锁,默认可重复读隔离级别,支持外键,支持MVCC
- MyISAM:不支持事务,只有表锁
索引
- BTree索引:底层是B+数,大多数场景选择BTree索引
- 哈希索引:底层哈希表,绝大多数情况下查询单条数据的时候,选择哈希索引,查询性能最快
- InnoDB和MyISAM对于BTree索引的不同实现:
- MyISAM的BTree索引:叶子节点的data域存放的数据记录的地址。在索引检索的时候,如果指定的key存在,则取出其data域,然后以data域的值为地址读取相应的数据记录,这被称为“非聚簇索引”。
- InnoDB的BTree索引:其数据文件本身就是索引文件。索引的key是数据表的主键,对应的叶子节点data域保存了完整的数据记录,这被称为“聚簇索引”。在根据主索引搜索时,直接找到key所在节点就可以取出数据;如果是辅助索引(不是主索引),则需要取出data域的值,也就是主键值,然后根据主索引取查找数据。
事务
ACID:原子性、隔离性、一致性、持久性
数据库并发引发的问题
- 脏读:一个事务中,读了另一个事务没有提交的数据。
- 丢失修改:第一个事务修改了一条数据还未提交,另一个事务也修改了这条数据,第一个提交,然后第二个事务提交,覆盖了第一个事务的修改结果。
- 不可重复读:一个事务中,但由于其他事务修改这条数据,导致多次读取的结果不一致。
- 幻读:T1事务读取了几行数据,接着T2事务插入了几行数据,导致在接下来的查询中T1事务发现的一些原本不存在的数据,就想幻觉一样。
- 不可重复读和幻读侧重点不一样,不可重复读是修改,比如多次读取一条记录发现其中某些字段被修改。幻读重点是新增或者删除,比如多次读取一条记录发现记录增多了或者减少了。
事务的隔离级别
- 读未提交
- 读已提交
- 可重复读
- 可串行化
Innodb默认隔离级别是可重复读REPEATABLE-READ 通过select @@tx_isolation,注意Innodb通过mvvc多版本控制,在可重复读的隔离级别下是可以预防幻读的。
锁机制 MyISAM采用表级锁,Innodb支持行锁,表锁,默认行锁
- 表级锁:锁住整张表,实现简单,资源消耗少,加锁快,不会出现死锁,并发低。
- 行级锁:锁住当前行,并发高,但是加锁开销大,加锁慢,会出现死锁。
InnoDB存储引擎的锁的三种算法:
- Record lock:单个行记录上的锁
- Gap lock:间隙锁,锁定一个范围,不包括记录本身
- Next-key lock:record+gap 索敌一个范围,包括记录本身
大表优化
- 限定数据的范围:查询语句必须限制数据范围,带上查询条件。
- 读/写分离:主库写,从库读
- 垂直分区:根据数据表的字段相关性,分出多个表
- 优点:列拆分,减少单表的数据量,减少I/O,易于维护。
- 缺点:主键会出现冗余,需要管理冗余列,会引起join操作,事务管理变的复杂。
- 水平分区:
- 根据某种策略存储数据分片,这样每一片数据分散到不同的表或者库中,达到分布式的目的。
数据库分片
- 客户端代理:分片的逻辑在应用端,封装在jar包中,通过修改或者封装JDBC来实现。当当网的Sharding-JDBC、阿里的TDDL
- 中间件代理:在应用端和数据库之间加了一个代理层。分片逻辑统一维护在中间件服务中。Mycat、360的Atlas、网易的DDB
分布式数据库id
- UUID,不适合主键,太长
- redis,性能好,但是增加维护成本
- Twitter的snowflake算法:Github 地址:https://github.com/twitter-archive/snowflake。
- 美团的leaf分布式ID生成器:https://tech.meituan.com/2017/04/21/mt-leaf.html 。