大家好,我是Tom哥~为了方便大家发现问题,看清全局,整理一个目录,我们可以快速全局的了解mysql数据库。面试官一般喜欢问什么问题接下来,我们来看看每个问题,一一回答。MyISAM和InnoDB的区别?答:InnoDB支持事务、外键、聚簇索引,通过MVCC支持高并发。索引和数据存储在一起。InnoDB不保存表的具体行数,执行selectcount(*)fromtable时需要全表扫描。MyISAM使用一个变量来保存整个表的行数。InnoDB最小的锁粒度是行锁,MyISAM最小的锁粒度是表锁,并发度低。MySQL使用InnoDB作为默认的存储引擎。mysql锁有哪几种类型?答:mysql的锁分为共享锁(S锁)、独占锁(X锁),也叫读锁和写锁。按照粒度可以分为表锁、页锁、行锁。什么是间隙锁?答:间隙锁只在可重复读级别可用。mysql会帮我们生成几个左开右闭的区间。结合MVCC和间隙锁可以解决幻读问题。如何避免死锁?答:死锁的四个必要条件:1.互斥2.请求保持3.循环等待4.非剥夺。合理设计索引,将差异化程度高的列放在复合索引的前面,让业务SQL通过索引定位到尽可能少的行,减少锁竞争。调整业务逻辑SQL的执行顺序,避免在事务前更新/删除长时间持有锁的SQL。避免大事务,将大事务拆分成多个小事务,以固定顺序访问表和行。例如,对于更新数据的两个事务,事务A更新数据的顺序是1、2;事务B更新数据的顺序是2、1,这样比较容易造成死锁。在并发比较高的系统中,不要显式加锁,尤其是在事务中。比如select...forupdate语句,如果是在一个事务中(starttransaction正在运行或者autocommit设置为0),那么找到的记录会被锁定。尝试使用主键/索引来查找记录。优化SQL和表设计,减少同时占用过多资源的情况。例如,避免多表连接,将复杂的SQL分解为多条简单的SQL。数据库的隔离级别?答:readuncommitted,readcommitted,repeatableread(mysql默认级别,每次读的结果都一样,但可能会出现幻读),序列化。Mysql有哪些类型的索引?答:普通索引:一个索引只包含一列,一张表可以有多个单列索引。唯一索引:索引列的值必须唯一,但允许空值复合索引:多个列值组成一个索引,专门用于组合查找,效率大于indexmergingClusteredindex:又称主键索引,是一种数据存储方式。B+Tree结构,非叶子节点包含键值和指针,叶子节点包含索引列和行数据。一张表只能有一个聚簇索引。非聚集索引:聚集索引或非聚集索引。叶节点仅存储索引列和主键ID。如果SQL需要返回索引列以外的其他字段信息,则需要返回表。第一个索引一般是顺序IO,回表操作是随机IO。回到牌桌的次数越多,表现就越差。这个时候我们推荐覆盖索引。什么是覆盖索引和返回表?答:1、覆盖索引是指在一次查询中,一个索引包含了所有需要查询的字段的值,可能是返回值,也可能是where条件selectbuyer_idfromorderwheremoney>100如果我们创建联合索引of(money,buyer_id),而索引的叶子节点包含了buyer_id的信息,我们就不回表查询了。2.回表就是查询的时候有些字段值取不到,需要重新查主键索引B+树。Mysql的最左前缀原则?答:即最左优先,在检索数据时,从联合索引的最左开始匹配,直到遇到范围查询(如:>、<、between、like等)。示例:其中a=1andb=2andc>3andd=4,如果创建组合索引(a,b,c,d),d将不会使用该索引;如果创建(a,b,d,c)的索引,两者都可以使用,a,b,d的顺序可以任意调整。在线SQL调优经验?答:1、将slow_query_log日志中收集到的慢sql结合explain分析是否命中索引。2.减少索引扫描行数,针对性优化慢SQL。3.建立联合索引。由于联合索引的每个叶子节点都包含了搜索字段的信息,所以按照最左前缀原则匹配后,再根据其他条件进行过滤,减少返回表的数据量。4.还可以使用虚拟列和联合索引来提高复杂查询的执行效率。为什么官方推荐使用自增id作为主键呢?答:自增id是连续的,插入过程也是顺序的。始终插入到末尾,减少分页,有效减少数据移动。所以尽量不要使用字符串(如:UUID)作为主键。为什么索引用B+树而不用B-树和红黑树呢?答:要提高查询速度,首先要减少磁盘IO次数,也就是降低树的高度。平衡二叉树和红黑树都是二叉树。时间复杂度为O(n)。当表的数据量在千万级时,树的深度很深,mysql读取时IO消耗很大。另外,InnoDB引擎以页为单位读取,每个节点一页,但是二叉树的每个节点存储一个关键字,造成空间浪费。在B-tree中,非叶子节点存储数据,占用更多空间,导致每个节点的指针少很多,无形中增加了树的深度。B+树数据存放在叶子节点,非叶子节点只存放键值+指针。索引树更扁平,三层深度可支持千万级表存储。同时,叶子节点通过链表关联,范围搜索更快。交易的特点是什么?答:酸。原子性。事务中的操作要么全部成功,要么全部失败。坚持。永久保存在数据库中。一致性。始终从一种一致状态过渡到另一种一致状态隔离。在一个事务的修改提交之前,其他事务是无法感知的。如何实现分布式事务?答:1.流水线任务,最终一致性,前提是接口支持幂等性2.事务消息3.两阶段提交4,三阶段提交5.在TCC6和Seata框架的日常工作中,如何优化MySQL?答:1、页面优化。比如电梯直达,限制100000,10先求初始主键id,然后通过id>#{value}取10项2.尽量使用覆盖索引。索引的叶子节点已经包含要查询的字段,减少查询次数表查询3、SQL优化(索引优化,小表驱动大表,虚列,适当增加冗余字段减少连表查询,联合索引、排序优化、慢日志解释分析执行计划)。4、设计优化(避免使用NULL,使用int等简单数据类型,减少文本类型,分库分表)。5、硬件优化(使用SSD减少I/O时间,网络带宽足够大,内存尽量大)mysql主从同步的具体过程?答:master主库,有数据更新,将本次更新的事件类型写入主库的binlog文件中,主库会创建一个logdump线程通知slave有数据更新slave,从master节点的logdump线程请求一份指定binlog文件位置的副本,并将请求的binlog保存到本地的Relaylog中,slave启动另一个SQL线程读取Relaylogevents并执行redo本地操作。在本地重新执行主库发生的事件,保证主从数据同步。什么是主从延迟?答:在主库执行完一个写SQL操作后,会有一次完整的数据同步到从库。这个时间差称为主从延迟。计算公式:主库生成一条写入SQL的binlog,里面会有time字段,写入记录的时间戳t1。binlog同步到从库后,一旦开始执行,取当前时间t2t2-t1,即延迟时间。注意:不同的服务器需要保持时钟一致。主从延迟故障排除方法?答:从showslavestatus命令输出的Seconds_Behind_Master参数的值来看,为零:说明主从复制良好正值:说明主从已经延迟,数字越大,表示也就是说从库延迟越严重,主从延迟怎么解决呢?答:这取决于业务的接受程度。如果延迟不能接受,建议强制主库查询。可以考虑引入缓存。更新主库后,同步写入缓存,保证缓存的时效性。改进从库机器配置,提高从库binlog的同步效率,缩短主从库。网络距离,减少binlog的网络传输时间。一主多从,每个从库启动一个线程从主库同步binlog,导致主库压力过大。Canal增量订阅&消费组件可以用来缓解主库的压力。因为数据库必须等到事务完成后才能写入binlog,所以减少大事务的执行,尽量控制数量,分批执行。5.6版本之前,从库是单线程的,遇到SQL执行慢的时候,会阻塞后续的同步。5.7版本之后支持多线程复制。可以在从服务上设置slave_parallel_workers为大于0的数,然后设置slave_parallel_type参数为LOGICAL_CLOCK为从库添加一个浮动IP,通过脚本检测从库的延迟。当延时大于指定阈值时,将浮动IP切换到主库,均衡后切换回从库。数据量太大怎么办?答:mysql表的数据量一般控制在千万级别。如果比较大,就要考虑分库分表了。除了分表,还列举了一些常见的海量数据业务的优化方式。缓存加速、读写分离、垂直拆分、分库分表、冷热数据分离、ES方便复杂搜索、NoSQL、NewSQL等分表后ID如何全局唯一?答:分库分表后,多个表共享一组全局id,原来的单表主键自增方式不能满足需求。我们需要重新设计一套id生成器。特点:全球唯一、高性能、高可用性、易访问。UUID数据库自增ID数据库的数段模式,每个业务定义初值和步长,一次拉取多个id号基于Redis,通过incr命令实现ID的原子自增。雪花算法(Snowflake)市面上的一些开源框架,如:百度(uid-generator)、美团(Leaf)、滴滴(Tinyid)等。分表后可能会遇到什么问题?答:分表后,与单表最大的区别是多了一个sharding_key,用于路由具体的物理表。以电子商务为例,有买家和卖家两个维度。通过buyer_id路由不能满足卖家的需求,反之亦然。如何解决?划分买家库和卖家库,将买家库作为写库,保存完整的数据关系。同时,同步一份异构数据到卖家数据库。卖家数据库只能存储seller_id、order_id、buyer_id等几个简单的关系字段,以seller_id为分表key进行多线程扫描,分段搜索,然后聚合结果。也可以存储在ES中,支持多维复杂搜索
