1. 索引
1、为什么要使用索引
2、什么样的信息能成于索引
主键、唯一键、普通键
3、索引的数据结构
二叉 查找数进行二分查找
B- TREE
B+ TREE
HASH
4、密集索引和稀疏索引的区别
密集索引:叶子节点不仅仅保存的键值,还保存位于同一行记录里的其他列信息。
稀疏索引:叶子节点仅保存键位信息和该行数据的地址,有的稀疏索引仅保存键位信息和主键。(二次查找)
由于密集索引决定了表的物理排列顺序,一个表只能有一个物理排列顺序,所以一个表只能创建一个密集索引。
myisam所有都是稀疏索引,innodb有且仅有一个密集索引。
innodb定义密集索引规则:
1、有主键,主键为密集索引
2、无主键、第一个唯一非空索引为密集索引
3、都没有,内部会生成一个隐藏主键
非主键索引存储相关键位信息和其对应的主键值,包含两次查找。
5、如何定位并优化慢查询sql
根据慢日志定位慢查询sql
slow_query_log_file xxx
slow_query_log on
long_query_time 1
show status like '%slow_queries%' 慢sql次数
set global slow_query_log= on; 打开慢日志
使用explain工具分析sql
type (index、all表明走的是全表扫描需优化)
extra(Using filesort【文件排序】 Using temporary【需要用到临时表】 需要优化)
一般保证查询达到range级别,最好达到ref。
修改sql或者尽量让sql走索引
6、联合索引的最左匹配原则成因
mysql会一直向右匹配直到遇到范围查询(> < between like )就停止匹配
a_b a= and b= a= 走 b= 不走
7、索引是创建的越多越好吗?
数据量小的表不需要建立索引,建立会增加额外的索引开销;数据变更需要维护索引,意味着需要索引建的越多需要更多的维护成本。
7、索引的一些潜规则
覆盖索引:
回表:
索引下推:
最左匹配:
2. MyISAM和Innodb关于锁方面的区别是什么?
前者默认表级锁,不支持行级锁。
后者默认行级锁,也支持表级锁
怎么显示给表加锁?
lock tables xxx(tableName) read(write)
unlock tables (释放锁)
读锁也叫共享锁
写锁也叫排他锁(sql语句后加上for update 显示加上排他锁)
先上读锁,再写,会block住
先上读锁,再读,不会block住
先上写锁,再读,会block住
先上写锁,再写,会block住
在rc隔离级别下,mysql只会对查询到的数据进行加锁。
Innodb默认自动提交事务
show variables like 'autocommit'
set autocommit=0 //关闭自动提交事务,只针对当前会话
lock in share mode 读锁
表级锁和索引无关,innodb在sql没有用到索引的时候走的是表级锁,用到索引走的是行级锁和gap锁。
myisam:
-
频繁执行全表count的语句
-
对数据增删改的频率不高,查询非常频繁
-
没有事务
innodb:
-
数据增删改查都相当频繁
-
可靠性要求比较高,要求支持事务
3. 数据库事务的四大特性?
ACID
原子性
一致性
隔离性
持久性
事务隔离级别以及各级别下的并发访问问题
事务并发访问引起的问题以及如何避免
| 事务隔离级别 | 更新丢失 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|---|
| 未提交读 | 避免 | 发生 | 发生 | 发生 |
| 已提交读 | 避免 | 避免 | 发生 | 发生 |
| 可重复读 | 避免 | 避免 | 避免 | 发生 |
| 串行化 | 避免 | 避免 | 避免 | 避免 |
mysql innodb默认隔离级别 可重复读
orcale 默认隔离级别 已提交读
Innodb可重复读隔离级别下如何避免幻读
表现:快照读(非阻塞读) 伪mvcc
内在:next-key 锁(行锁+gap锁)
4. 数据库语法部分
group by
group by 里出现某个表的字段,select里面的列要么是group by里面出现的列,要么是别的表的列,要么是带函数的列。
having
通常和group by 一起执行
where过滤行,having过滤组
出现在同一sql的顺序:where>group by >having
sum、count、max、min、avg
5. 数据库分库发表
- 为什么要分库分表?
分库分表一定是为了支撑高并发、数据量大两个问题
- 用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?
比较常见的包括:cobar、TDDL、atlas、sharding-jdbc、mycat
cobar:阿里b2b团队开发和开源的,属于proxy层方案。早些年还可以用,但是最近几年都没更新了,基本没啥人用,差不多算是被抛弃的状态吧。而且不支持读写分离、存储过程、跨库join和分页等操作。
TDDL:淘宝团队开发的,属于client层方案。不支持join、多表查询等语法,就是基本的crud语法是ok,但是支持读写分离。目前使用的也不多,因为还依赖淘宝的diamond配置管理系统。
atlas:360开源的,属于proxy层方案,以前是有一些公司在用的,但是确实有一个很大的问题就是社区最新的维护都在5年前了。所以,现在用的公司基本也很少了。
sharding-jdbc:当当开源的,属于client层方案。确实之前用的还比较多一些,因为SQL语法支持也比较多,没有太多限制,而且目前推出到了2.0版本,支持分库分表、读写分离、分布式id生成、柔性事务(最大努力送达型事务、TCC事务)。而且确实之前使用的公司会比较多一些(这个在官网有登记使用的公司,可以看到从2017年一直到现在,是不少公司在用的),目前社区也还一直在开发和维护,还算是比较活跃,个人认为算是一个现在也可以选择的方案。
mycat:基于cobar改造的,属于proxy层方案,支持的功能非常完善,而且目前应该是非常火的而且不断流行的数据库中间件,社区很活跃,也有一些公司开始在用了。但是确实相比于sharding jdbc来说,年轻一些,经历的锤炼少一些。
所以综上所述,现在其实建议考量的,就是sharding-jdbc和mycat,这两个都可以去考虑使用。
sharding-jdbc这种client层方案的优点在于不用部署,运维成本低,不需要代理层的二次转发请求,性能很高,但是如果遇到升级啥的需要各个系统都重新升级版本再发布,各个系统都需要耦合sharding-jdbc的依赖;
mycat这种proxy层方案的缺点在于需要部署,自己及运维一套中间件,运维成本高,但是好处在于对于各个项目是透明的,如果遇到升级之类的都是自己中间件那里搞就行了。
通常来说,这两个方案其实都可以选用,但是我个人建议中小型公司选用sharding-jdbc,client层方案轻便,而且维护成本低,不需要额外增派人手,而且中小型公司系统复杂度会低一些,项目也没那么多;
但是中大型公司最好还是选用mycat这类proxy层方案,因为可能大公司系统和项目非常多,团队很大,人员充足,那么最好是专门弄个人来研究和维护mycat,然后大量项目直接透明使用即可。
我们,数据库中间件都是自研的,也用过proxy层,后来也用过client层
- 你们具体是如何对数据库如何进行垂直拆分或水平拆分的?
水平拆分的意思,就是把一个表的数据给弄到多个库的多个表里去,但是每个库的表结构都一样,只不过每个库表放的数据是不同的,所有库表的数据加起来就是全部数据。水平拆分的意义,就是将数据均匀放更多的库里,然后用多个库来抗更高的并发,还有就是用多个库的存储容量来进行扩容。
垂直拆分的意思,就是把一个有很多字段的表给拆分成多个表,或者是多个库上去。每个库表的结构都不一样,每个库表都包含部分字段。一般来说,会将较少的访问频率很高的字段放到一个表里去,然后将较多的访问频率很低的字段放到另外一个表里去。因为数据库是有缓存的,你访问频率高的行字段越少,就可以在缓存里缓存更多的行,性能就越好。这个一般在表层面做的较多一些。
- 如何系统平滑地迁移到分库分表上面去
1、停机迁移方案
2、双写迁移方案
-
如何设计可以动态扩容缩容的分库分表方案?
-
分库分表之后,id主键如何处理?
1、数据库自增id
2、snowflake算法
- 如何实现mysql的读写分离?
其实很简单,就是基于主从复制架构,简单来说,就搞一个主库,挂多个从库,然后我们就单单只是写主库,然后主库会自动把数据给同步到从库上去。
- MySQL主从复制原理的是啥?
主库将变更写binlog日志,然后从库连接到主库之后,从库有一个IO线程,将主库的binlog日志拷贝到自己本地,写入一个中继日志中。接着从库中有一个SQL线程会从中继日志读取binlog,然后执行binlog日志中的内容,也就是在自己本地再次执行一遍SQL,这样就可以保证自己跟主库的数据是一样的。
这里有一个非常重要的一点,就是从库同步主库数据的过程是串行化的,也就是说主库上并行的操作,在从库上会串行执行。所以这就是一个非常重要的点了,由于从库从主库拷贝日志以及串行执行SQL的特点,在高并发场景下,从库的数据一定会比主库慢一些,是有延时的。所以经常出现,刚写入主库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能读取到。
而且这里还有另外一个问题,就是如果主库突然宕机,然后恰好数据还没同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。
所以mysql实际上在这一块有两个机制,一个是半同步复制,用来解决主库数据丢失问题;一个是并行复制,用来解决主从同步延时问题。
这个所谓半同步复制,semi-sync复制,指的就是主库写入binlog日志之后,就会将强制此时立即将数据同步到从库,从库将日志写入自己本地的relay log之后,接着会返回一个ack给主库,主库接收到至少一个从库的ack之后才会认为写操作完成了。
所谓并行复制,指的是从库开启多个线程,并行读取relay log中不同库的日志,然后并行重放不同库的日志,这是库级别的并行。
- bin log和relay log
bin log
- 二进制文件
- binlog在mysql的server层实现(引擎其用)
- binlog是逻辑日志,记录的是一条语句的原始逻辑。
- binlog不限大小,追加写入,不会覆盖之前的日志