来源 | 科技缪缪

想进大厂,mysql不会那可不行,来接受mysql面试挑战吧,看看你能坚持到哪里?

能说下 myisam 和 innodb 的区别吗?

myisam引擎是5.1版本之前的默认引擎,支持全文检索、压缩、空间函数等,但是不支持事务和行级锁,所以一般用于有大量查询少量插入的场景来使用,而且myisam不支持外键,并且索引和数据是分开存储的。innodb是基于聚簇索引建立的,和myisam相反它支持事务、外键,并且通过MVCC来支持高并发,索引和数据存储在一起。

说下mysql的索引有哪些吧,聚簇和非聚簇索引又是什么?

索引按照数据结构来说主要包含B+树和Hash索引。假设我们有张表,结构如下:

create table user(id int(11) not null,
  age int(11) not null,
  primary key(id),key(age)
);

B+树是左小右大的顺序存储结构,节点只包含id索引列,而叶子节点包含索引列和数据,这种数据和索引在一起存储的索引方式叫做聚簇索引,一张表只能有一个聚簇索引。假设没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有的话则会隐式定义一个主键作为聚簇索引。


这是主键聚簇索引存储的结构,那么非聚簇索引的结构是什么样子呢?非聚簇索引(二级索引)保存的是主键id值,这一点和myisam保存的是数据地址是不同的。


最终,我们一张图看看InnoDB和Myisam聚簇和非聚簇索引的区别。


 那你知道什么是覆盖索引和回表吗?

覆盖索引指的是在一次查询中,如果一个索引包含或者说覆盖所有需要查询的字段的值,我们就称之为覆盖索引,而不再需要回表查询。而要确定一个查询是否是覆盖索引,我们只需要explain sql语句看Extra的结果是否是“Using index”即可。以上面的user表来举例,我们再增加一个name字段,然后做一些查询试试。

explain select * from user where age=1; //查询的name无法从索引数据获取explain select id,age from user where age=1; //可以直接从索引获取

 锁的类型有哪些呢mysql锁分为共享锁排他锁,也叫做读锁和写锁。读锁是共享的,可以通过lock in share mode实现,这时候只能读不能写。写锁是排他的,它会阻塞其他的写锁和读锁。从颗粒度来区分,可以分为表锁行锁两种。表锁会锁定整张表并且阻塞其他用户对该表的所有读写操作,比如alter修改表结构的时候会锁表。行锁又可以分为乐观锁悲观锁,悲观锁可以通过for update实现,乐观锁则通过版本号实现。

你能说下事务的基本特性和隔离级别吗?

事务基本特性ACID分别是:原子性指的是一个事务中的操作要么全部成功,要么全部失败。一致性指的是数据库总是从一个一致性的状态转换到另外一个一致性的状态。比如A转账给B100块钱,假设中间sql执行过程中系统崩溃A也不会损失100块,因为事务没有提交,修改也就不会保存到数据库。隔离性指的是一个事务的修改在最终提交前,对其他事务是不可见的。持久性指的是一旦事务提交,所做的修改就会永久保存到数据库中。而隔离性有4个隔离级别,分别是:read uncommit读未提交,可能会读到其他事务未提交的数据,也叫做脏读。用户本来应该读取到id=1的用户age应该是10,结果读取到了其他事务还没有提交的事务,结果读取结果age=20,这就是脏读。


read commit 读已提交,两次读取结果不一致,叫做不可重复读。

不可重复读解决了脏读的问题,他只会读取已经提交的事务。用户开启事务读取id=1用户,查询到age=10,再次读取发现结果=20,在同一个事务里同一个查询读取到不同的结果叫做不可重复读。


repeatable read 可重复复读,这是mysql的默认级别,就是每次读取结果都一样,但是有可能产生幻读。

serializable串行,一般是不会使用的,他会给每一行读取的数据加锁,会导致大量超时和锁竞争的问题。

那ACID靠什么保证的呢?

A原子性由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql。C一致性一般由代码层面来保证。I隔离性由MVCC来保证。D持久性由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复。

那你说说什么是幻读,什么是MVCC?

要说幻读,首先要了解MVCC,MVCC叫做多版本并发控制,实际上就是保存了数据在某个时间节点的快照。我们每行数实际上隐藏了两列,创建时间版本号,过期(删除)时间版本号,每开始一个新的事务,版本号都会自动递增。还是拿上面的user表举例子,假设我们插入两条数据,他们实际上应该长这样。

这时候假设小明去执行查询,此时current_version=3:

select * from user where id<=3;

同时,小红在这时候开启事务去修改id=1的记录,current_version=4:

update user set name='张三三' where id=1;

执行成功后的结果是这样的:

如果这时候还有小黑在删除id=2的数据,current_version=5,执行后结果是这样的。

由于MVCC的原理是查找创建版本小于或等于当前事务版本,删除版本为空或者大于当前事务版本,小明的真实的查询应该是这样:

select * from user where id<=3 and create_version<=3 and (delete_version>3 or delete_version is null);

所以小明最后查询到的id=1的名字还是'张三',并且id=2的记录也能查询到。这样做是为了保证事务读取的数据是在事务开始前就已经存在的,要么是事务自己插入或者修改的。明白MVCC原理,我们来说什么是幻读就简单多了。举一个常见的场景,用户注册时,我们先查询用户名是否存在,不存在就插入,假定用户名是唯一索引。

1、小明开启事务current_version=6查询名字为'王五'的记录,发现不存在。

2、小红开启事务current_version=7插入一条数据,结果是这样:

3、小明执行插入名字'王五'的记录,发现唯一索引冲突,无法插入,这就是幻读。

那你知道什么是间隙锁吗?

间隙锁是可重复读级别下才会有的锁,结合MVCC和间隙锁可以解决幻读的问题。我们还是以user举例,假设现在user表有几条记录:当我们执行:

begin;select * from user where age=20 for update;begin;insert into user(age) values(10); #成功insert into user(age) values(11); #失败insert into user(age) values(20); #失败insert into user(age) values(21); #失败insert into user(age) values(30); #失败

只有10可以插入成功,那么因为表的间隙mysql自动帮我们生成了区间(左开右闭)。

(negative infinity,10],(10,20],(20,30],(30,positive infinity)

由于20存在记录,所以(10,20],(20,30]区间都被锁定了无法插入、删除。如果查询21呢?就会根据21定位到(20,30)的区间(都是开区间)。需要注意的是唯一索引是不会有间隙索引的。

你们数据量级多大?分库分表怎么做的?

首先分库分表分为垂直和水平两个方式,一般来说我们拆分的顺序是先垂直后水平。垂直分库基于现在微服务拆分来说,都是已经做到了垂直分库了。


垂直分表

如果表字段比较多,将不常用的、数据较大的等等做拆分。


水平分表

首先根据业务场景来决定使用什么字段作为分表字段(sharding_key),比如我们现在日订单1000万,我们大部分的场景来源于C端,我们可以用user_id作为sharding_key,数据查询支持到最近3个月的订单,超过3个月的做归档处理,那么3个月的数据量就是9亿,可以分1024张表,那么每张表的数据大概就在100万左右。比如用户id为100,那我们都经过hash(100),然后对1024取模,就可以落到对应的表上了。

那分表后的ID怎么保证唯一性的呢?

因为我们主键默认都是自增的,那么分表之后的主键在不同表就肯定会有冲突了。有几个办法考虑:

  1. 设定步长,比如1-1024张表我们分别设定1-1024的基础步长,这样主键落到不同的表就不会冲突了。
  2. 分布式ID,自己实现一套分布式ID生成算法或者使用开源的比如雪花算法这种。
  3. 分表后不使用主键作为查询依据,而是每张表单独新增一个字段作为唯一主键使用,比如订单表订单号是唯一的,不管最终落在哪张表都基于订单号作为查询依据,更新也一样。

分表后非sharding_key的查询怎么处理呢?

  1. 可以做一个mapping表,比如这时候商家要查询订单列表怎么办呢?不带user_id查询的话你总不能扫全表吧?所以我们可以做一个映射关系表,保存商家和用户的关系,查询的时候先通过商家查询到用户列表,再通过user_id去查询。

  2. 打宽表,一般而言,商户端对数据实时性要求并不是很高,比如查询订单列表,可以把订单表同步到离线(实时)数仓,再基于数仓去做成一张宽表,再基于其他如es提供查询服务。

  3. 数据量不是很大的话,比如后台的一些查询之类的,也可以通过多线程扫表,然后再聚合结果的方式来做。或者异步的形式也是可以的。
ListList>> taskList = Lists.newArrayList();for (int shardingIndex = 0; shardingIndex 1024; shardingIndex++) {    taskList.add(() -> (userMapper.getProcessingAccountList(shardingIndex)));}List list = null;try {list = taskExecutor.executeTask(taskList);} catch (Exception e) {//do something}public class TaskExecutor {public  List executeTask(Collection extends Callable> tasks) throws Exception {List result = Lists.newArrayList();List> futures = ExecutorUtil.invokeAll(tasks);for (Future future : futures) {            result.add(future.get());        }return result;    }}

说说mysql主从同步怎么做的吧?

首先先了解mysql主从同步的原理

  1. master提交完事务后,写入binlog。
  2. slave连接到master,获取binlog。
  3. master创建dump线程,推送binglog到slave。
  4. slave启动一个IO线程读取同步过来的master的binlog,记录到relay log中继日志中。
  5. slave再开启一个sql线程读取relay log事件并在slave执行,完成同步。
  6. slave记录自己的binglog。

由于mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。由此产生两个概念。

全同步复制主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。半同步复制和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。

那主从的延迟怎么解决呢?

这个问题貌似真的是个无解的问题,只能是说自己来判断了,需要走主库的强制走主库查询。

更多阅读推荐

  • 超详细 | 21张图带你领略集合的线程不安全

  • 云起云涌:PaaS 体系架构与运维系统上云实践

  • 该买哪家二手手机呢?程序员爬取京东告诉你!

  • 苹果秋季发布会于9月16日召开;华为搜索业务将在国内亮相;Android 11正式版发布 | 极客头条

  • 腾讯微博即将关停,十年了,你用过吗?

mysql delete 会锁表吗_我想进大厂之 MYSQL 夺命连环13问相关推荐

  1. 《我想进大厂》之mysql夺命连环13问

    想进大厂,mysql不会那可不行,来接受mysql面试挑战吧,看看你能坚持到哪里? 1. 能说下myisam 和 innodb的区别吗? myisam引擎是5.1版本之前的默认引擎,支持全文检索.压缩 ...

  2. mysql delete 会锁表吗_MySQL高压缩引擎TokuDB 揭秘

    原文出处:http://mysql.taobao.org/monthly/2017/07/04/ HybridDB for MySQL(原名petadata)是面向在线事务(OLTP)和在线分析(OL ...

  3. 听说你想进大厂?当心这13个MySQL送命题!

    想进大厂,mysql不会那可不行,来接受mysql面试挑战吧,看看你能坚持到哪里? 1. 能说下myisam 和 innodb的区别吗? myisam引擎是5.1版本之前的默认引擎,支持全文检索.压缩 ...

  4. Mysql 会导致锁表的语法

    转自:http://blog.csdn.net/lifaming15/article/details/47904557 最近再找一些MySQL锁表原因,整理出来一部分sql语句会锁表的,方便查阅,整理 ...

  5. 你想进大厂吗?这份所有大厂都绕不过的MySQL宝典值得你一看

    前言: 好久没有给我的粉丝们分享过资料了,眼看着秋招就来了特意给大家总结了一份大厂秋招宝典,如今基本上所有的大厂都绕不过MySQL只要你想进大厂不管是腾讯.阿里也好还是字节百度只要你去面试就一定会问你 ...

  6. oracle锁表查询_专业解决 MySQL 查询速度慢与性能差

    Java识堂,一个高原创,高收藏,有干货的微信公众号,一起成长,一起进步,欢迎关注 什么影响了数据库查询速度 1.1 影响数据库查询速度的四个因素 1.2 风险分析 QPS: QueriesPerSe ...

  7. mysql 数据库查看锁表_【数据库】MySQL查看是否锁表

    可直接在mysql命令行执行:show engine innodb status\G; 查看造成死锁的sql语句,分析索引情况,然后优化sql然后show processlist; 推荐课程:MySQ ...

  8. mysql 查询 锁表_怎么查找mysql中的锁表语句?

    查看sql server数据库被锁表可以用用如下语句: 也可以用如下语句: 拓展资料: 锁定数据库的一个表的区别SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取 ...

  9. mysql行级锁 表级锁 页级锁详细介绍_MySQL行级锁、表级锁、页级锁详细介绍

    页级:引擎 BDB. 表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行 行级:引擎 INNODB , 单独的一行记录加锁 表级,直接锁定整张表,在你锁定期间,其它进程无法对该表进行写 ...

最新文章

  1. IBM全面拥抱Linux,为“认知商业”提供POWER
  2. PHPStudy下Apache SSL证书安装教程
  3. [推荐]大量 Blazor 学习资源(二)
  4. Linux中几个实用快捷键
  5. js 密码强弱的实现
  6. RxJS异步编程的简介
  7. python reduce函数怎么用_python内置函数reduce
  8. PHP正则表达式的快速学习方法
  9. Spark安装部署:Standalone模式
  10. 《Python金融大数据风控建模实战》 第14章 决策树模型
  11. 求长方形和正方形的周长
  12. 硬件工程师有没有35岁危机?
  13. 你为什么要离开上一家公司?
  14. NX2007软件下载
  15. HC-SR04 超声波测距模块说明
  16. 张勋说:关于棒磨机的历史 你了解多少?(图文)
  17. Springboot整合redis从安装到FLUSHALL
  18. 2015/5/2日-月总结
  19. 自制RC自动驾驶+遥控智能小车
  20. c# 小票机打印二维条码_C# winform 使用rdlc打印小票其中包含动态显示多条形码的解决方法...

热门文章

  1. 云栖大会,未来万物皆是计算机?
  2. 笔记本 Window 7下硬盘安装 mint 13遇到的问题及解决方案(Ubuntu亦可)
  3. 管理就是管人,那究竟怎么管?
  4. HTML之video标签
  5. 鼠标悬浮 鼠标移上 移出事件时 改变背景颜色
  6. GoodSync新用户快速入门学习篇
  7. 股票策略 —— 指数择时 + 因子选股2
  8. 小刘总——王者荣耀抽荣耀水晶玄学
  9. python的if else 语句使得循环停止的_Python条件语句和循环语句
  10. 苹果手机录音m4a格式怎么转成mp3