1. 索引的基本原理
原理:
排好序的数据结构,用来快速查找某些特定值的记录。
2. Mysql聚簇和非聚簇索引的区别
- 聚簇索引:数据和索引放在一块,找到了索引就找到了数据;
- 非聚簇索引:数据和索引分开存放,需要先找到索引,拿到地址,才能找到数据。
在InnoDB中,一定是有主键的,主键一定是聚簇索引(在叶子节点中,同时保存了索引和数据)。非主键为非聚簇索引,叶子节点中存储的是主键。
如果使用了非主键索引,如果没有采用覆盖索引,就需要至少两次查询:
- 查询非主键索引,拿到主键;
- 通过主键去查询主键索引。
这个过程就叫做回表。
在MyISM中,使用的是非聚簇索引,也是采用B+树,只是叶子节点中不保存数据,而是保存数据的地址。
3. Mysql的锁了解哪些
按粒度分:
- 行锁,锁一行,粒度最小,并发度最高
- 表锁,锁整张表,粒度最大,并发度最小
- 间隙锁,就是锁一个区间
按是否共享, 是针对事务而言的:
- 共享锁:就是读锁,一个事务给某行加了读锁,其他事务仍然可以读,但是不可以写;
- 排他锁:就是写锁,一个事务给某行加了写锁,其他事务不可以读也不可以写,其实很好理解,加了写锁以后,数据可能会变化,那么其他事务读出来的数据是不准确的,因此不允许其他事务进行读和写。
还可以分为:
- 乐观锁,通过版本号实现,其实没加锁,只是比对版本号是否匹配
- 悲观锁, 加锁了,例如行锁,表锁。
4. 海量数据下,如何快速查找一条记录(Redis)
- 使用布隆过滤器,快速过滤不存在的记录;
- 解释一下布隆过滤器的原理, bitmap,多种哈希
- 在Redis中建立数据缓存
- 例如,用String类型存储,userId -> user.json
- 例如,用Hash类型存储,userId -> field1, field2, field3 … -> value1, value2, value3
- 为了减少Redis中Key占用,可以用UserInfo作为总的key,field就用UserId,value就用user.json
- 要考虑缓存击穿问题,虽然采用了布隆过滤器,但是又误判率,还是会去查底层数据库,采用分布式锁重建缓存。或者定期重建缓存。
- 查询优化,按槽位分配数据,自己实现槽位计算,找到记录应该分配到哪台机器上,直接去目标机器上找。·
5. 事务的基本特性和隔离级别
基本特性:
ACID
原子性:
事务中的操作要么全部成功,要么全部失败,例如转账
一致性:
C其实依赖于程序员,并不是事务直接提供的,我们要通过AID来保证C。一致性就是事务执行前后,不会破坏我们的约束。例如只有90块钱,但想转出100块,我们的约束是余额不能小于0,那么不能允许该事务执行成功。因为一旦成功了,余额会小于0,破坏了我们业务上的约束。
隔离性:
隔离级别就是和隔离性有关的,隔离性指的是,不同事务在提交完成后,表现出来应该是串行的,比如事务A让余额增加了200, 事务B让余额增加了100,最终的表现形式应该是增加了300。然而如果真的采用串行处理事务的话,效率很低。因此Mysql有4个不同的隔离级别,来做妥协,提高效率。
持久性:
事务一旦提交,所做的修改就会永久保存到数据库中。
隔离级别:
- Read Uncommited: 读未提交,指的是事务B有可能会读到事务A未提交的数据,这就会导致脏读。脏读是最不可被接受的。
- Read Commited: 读已提交,指的是事务B只能去读取其他事务已经提交的数据,解决了脏读问题。但是还是会出现不可重复读的问题,例如:
- A将余额改成500, B读取到了500;
- C将余额改成了200,B再次读取时读到了200;
- 虽然是正确是值,但是在同一次事务的两次读取过程中,B的值前后不一致,因此是不可重复读。
不可重复读的问题在某些业务场景下是可以接受的,如果在你的业务场景下不能接受,说明这种隔离级别还不够,需要增强隔离级别。
- Repeatable Read:可重复读。是Mysql默认的级别,每次读取的结果都是一样的。首先,它读取的一定是事务提交以后的数据,所以不会出现脏读,其次,它只要读取过一次了,那么接下来该事务中的每次读取都是同一个值,即便其他事务update了这个值。虽然不受Update的影响,但是会受Insert操作的影响。Insert会导致幻读的出现,
- 即事务A : Select一个范围内的数据时,读到1,2,3,4, 6
- 事务B:插入一条数据5,
- 事务A再次读取,拿到1,2,3,4,5,6
6. ACID靠什么保证
原子性:
由undo log日志保证,记录需要回滚的日志信息,撤销已经执行成的SQL,说白了就是sql的反向执行。
一致性:
由其他AID来保证,从而达到一致性
隔离性:
MVCC,多版本控制保证
持久性:
由内存 + redo log保证,mysql修改数据的同时会在redo log记录本次操作,如果宕机则从redo log恢复。
7. Mysql如何搭建集群
- Mysql通过将主节点的Binlog同步给从结点,完成主从间数据同步。
- 步骤1不会反过来,因此我们需要做读写分离,只允许主节点进行写入。如果多个结点都能写,那么数据会变得混乱。
8. Mysql分库分表
通常指水平分片,即将一个很大的表进行拆分,分到多个不同的数据库去。
策略:
策略1:取模,模为0去0号库,模为1去1号库。
取模的缺点是不好扩展,一旦要扩展到三个库就蒙圈了,所有数据都要移动。
策略2:按范围分片,比如按时间,同一个月的数据放在同一个库。
缺点是数据不够平均,例如每个月的数据量不相同。
阿里提供的开发手册中,建议一个表的数据量超过500W或者数据文件超过2G,就要考虑分库分表了。
分库分表后的执行流程:
SQL解析 -> 查询优化 -> 路由(最重要)到正确的库上