[Java复习] 面试突击 - MySQL

MySQL 几大部分存储引擎、索引、事务、锁

MySQL的MyISAM和InnoDB存储引擎的区别是啥?

myisam,不支持事务,不支持外键约束,索引文件和数据文件分开,这样在内存里可以缓存更多的索引,对查询的性能会更好,适用于那种少量的插入,大量查询的场景。

innodb,主要特点就是支持事务,走聚簇索引,强制要求有主键,支持外键约束,高并发、大数据量、高可用等相关成熟的数据库架构,分库分表、读写分离、主备切换,全部都可以基于innodb存储引擎。

聊聊MySQL的索引实现原理?各种索引你们平时都怎么用的?

  • MySQL索引的原理和数据结构能介绍一下吗?
  • b+树和b-树有什么区别?
  • Myisam和Innodb存储引擎的索引实现?
  • MySQL聚簇索引和非聚簇索引的区别是什么?
  • 他们分别是如何存储的?
  • 使用MySQL索引都有哪些原则?
  • MySQL复合索引如何使用?

先说什么索引?

索引就是用一个数据结构组织某一个列数据,然后根据这一列数据查询时,不用全表扫描,根据特定数据结构找到那一列的值,然后找到对应行的物理地址。

先说b-树,画图如下:

查找时,从根节点开始二分查找。

b+树是b-树的变形,不一样的地方:

B-和B+树区别:

1. B+树只有叶子节点存储数据,其他中间节点只有索引没有数据,同样的大小的磁盘页可以容纳更多的节点元素。相同数量下,B+树更“矮胖”,查询IO次数更少

2. B+树查询必须查找叶子节点,B+树查询更稳定(并不慢)。B-树查询性能不稳定,最好只查根节点,最坏查到叶子节点。

3. B+树范围查询更简便。B+树中序遍历要简单得多

Myisam和Innodb存储引擎的索引实现?

myisam的索引中,每个叶子节点的data存放的是数据行的物理地址,每行对应一个物理地址。数据文件单独存放一个文件。最大特点是数据文件和索引文件是分开的。

innodb的数据文件本身就是索引文件,必须有主键,会根据主键建立一个默认索引,叫聚簇索引

innodb下,对某个非主键字段创建索引,那么最后那个叶子节点的值就是主键的值,再用主键的值到聚簇索引里查找到数据,叫回表

innodb,建议统一用auto_increment自增值作为主键,可以保持聚簇索引直接加记录,不用修改原来b+树的结构,浪费时间。

索引常见使用规则?

比如product表,创建索引:

create index (shop_id, product_id, gmt_create)

1. 全列匹配

where条件正好用到这3个字段,就用到联合索引

2. 最左前缀匹配

SQL里,正好用到联合索引最左边的一个或几个列表。

3. 最左前缀匹配,但中间某个值没有匹配

如果sql用了联合索引第一列和第三列,会按照第一列在索引里找,找完后对结果集根据第三列做全表扫描,不会走第三列的索引了。

4. 前缀匹配

如果不是等值,或比如=, >, <=等操作,而是Like操作。则只有Like ‘xx%’ (%在最后)这种才能用上索引。

5. 范围匹配

只有符号最左前缀的列的范围才用到索引,范围之后的列用不到索引。

比如: select * from product where shop_id >= 1 and product_id = 1;

这里就只用到shop_id索引。

6. 包含函数

对某个列用了函数,则该列不走索引。

索引缺点以及使用注意?

常见缺点:增加磁盘消耗,占用磁盘文件,同时高并发频繁插入和修改索引,会导致性能损耗。

使用注意:1. 尽量创建少的索引,一个表,两三个。

2. 一个字段的值几乎都不太一样的,比如id,这样用索引效果最好。

小结:

互联网系统中,一般尽量降低SQL复杂度,用简单的主键索引(聚簇索引)+少数联合索引,

可以覆盖一个表的所有SQL查询,更复杂的业务逻辑,应该放在Java代码里实现。

SQL越简单,后面迁移,分库分表,读写分离的成本更低,减少对SQL的改造。

MySQL最好用在在线及时存储,不要用于计算(Join, 子查询,函数等等)。高并发场景下,计算放在Java内存里

说说事务的几个特性是啥?有哪几种隔离级别?

特性:ACid

原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

隔离级别:

1. 读未提交

事务A把id=1, name=张三修改为李四,但是还未提交,这时事务B已经看到id=1的name为李四了。

  2. 读已提交(不可重复读)

事务A把id=1, name=张三修改为李四,但是还未提交。事务B第一次读,读到是张三,看不见李四。

紧接着事务A提交了事务,事务A在第二次读的时候,读到的是修改后的李四。

这个也叫不可重复读,就是所谓一个事务内对一个数据的两次读,可能读到不一样的值。

  3. 可重复读

无论事务A什么时候把张三修改为李四,事务B不管什么时刻读到值,都是事务B刚开启时读到的值。事务开启后对一行读取的值都是一样的。

      幻读(不是隔离级别):事务A第一次查询所有数据,就一行id=1。后面事务B插入一行数据id=2,事务A查询时发现2条数据,感觉发生幻觉。

针对数据件数发生变化。

   4. 串行化

      事务A运行期间,事务B不允许运行。事务A提交完事务后,事务B才开始运行。串行化是为了解决幻读。

MySQL是怎么实现可重复读的?

MySQL是通过MVCC机制来实现的,就是多版本并发控制(Multi-Version Concurrency Control)。

Innodb存储引擎会在每行数据最后增加两个隐藏列

一个保证行的创建时间,一个保存行的删除时间,但这里存放的不是时间,是事务id,事务id是mysql自己维护的自增,全局唯一。

举例1:
  id name   创建事务id   删除事务id
  1 张三     101      空

事务id=101的事务查询id=1的这一行,一定能找到创建事务id<=当前事务id的一行。
    当事务id=102把id=1的一行删除了,这时id=1的行的删除事务id设置为102.

id name   创建事务id   删除事务id
1  张三     101      102

事务id=101的事务,再次查询id=1的行,仍然能查到。因为创建事务id<=当前事务id,且当前事务id<删掉事务id。

举例2:(同一行被修改)
id   name   创建事务id   删除事务id
2  李四     201      空
2  王五     202      空

事务201创建了id=2的数据,事务202修改了id=2的数据,把name修改为王五,这时候事务201仍然可以查询到创建事务id<=当前事务id的数据,

查不到比自己创建事务id大的记录。

MySQL就是通过MVCC实现可重复读,事务可以读取该事务启动时创建事务id的记录,读不到后面事务的版本。

说说MySQL数据库锁的实现原理吗?如果死锁了咋办?

数据库锁有哪些类型?锁如何实现的?MySQL行级锁有哪两种?一定会锁指定行吗?为什么?

悲观锁和乐观锁是什么?使用场景是什么?

MySQL的死锁原理以及如何定位和解决?

1. MySQL锁

锁类型:表锁行锁页锁

myisam一般加表锁,查询时,默认加共享锁,也就是表读锁,别人可以查,但不能写;

myisam写的时候,加表独占锁,也就是表写锁,别人不能读也不能写。现在用的很少。

 

innodb的行锁分共享锁(S)和排他锁(X)。

共享锁,多个事务可以加共享锁读同一行数据,但别的事务不能写这行数据;

排他锁,一个事务可以写这行数据,别的事务只能读不能写。

  innodb表锁,分成意向共享锁,就是加共享行锁的时候,必须先加这个共享表锁;

还有一个意向排他锁,给某行加排他锁的时候,必须先给表加排他锁。这个表锁,是innodb引擎自动加的。

insert、update、delete时,innodb会自动为这一行加行级的排他锁。

select时,innodb啥锁都不加,默认实现可重复读,MVCC机制,所有多个事务随便读一个数据,不会有冲突,大家读的是自己的快照,不涉及锁。

  手动加共享锁

select * from table where id=1 lock in share mode; //id=1这行加了共享锁,其他事务不能修改

  手动加排他锁(悲观锁)

select * from table where id=1 for update; //id=1这行加了排他锁,表示该事务准备修改,其他事务被卡住等待。慎用!线上一般不用,容易出问题。

  乐观锁:

select id, name, version from table where id = 1;

update table set name=’new name’, version = version + 1 where id = 1 and version = 1;

每次修改比较这条数据和之前查出的数据版本号是否一致,一致就修改并且版本号+1,否则就不更新。

乐观锁可以提高并发访问的效率,但是如果出现了冲突只能向上抛出,然后重来一遍;悲观锁可以避免冲突的发生,但是会降低效率。

 高并发场景用乐观锁!

  死锁:

事务A,B对自己的资源持有锁的同时,又要去请求对方持有的锁,结果谁也拿不到锁,导致死锁。

死锁排查,查看死锁日志,找到对应的sql,找到代码,具体判断为什么死锁。

MySQL的SQL调优一般都有哪些手段?你们一般怎么做?

1. SQL慢,一般就是没有用索引。看执行计划,有没有走索引。

explain select * from table

table|type|possible_keys|key|key_len|ref|rows|extra

table: 哪个表

type: 类型  all:全部扫描  const:读常量,最多一条记录匹配  eq_ref:走主键,一般最多一条记录  index:扫描全部索引  range: 扫描部分索引  possible_keys: 显示可能使用的索引

key: 实际使用的索引

key_len: 使用索引的长度

ref: 联合索引哪一列被用到

rows: 一共扫描和返回了多少行

extra: using filesort:需要额外进行排序, using temporary: mysql构建了临时表,比如排序的时候 using where:就是对索引扫描出来的数据再次根据where来过滤出结果

参考资料:

互联网Java工程师面试突击(第三季)-- 中华石杉

原文地址:https://www.cnblogs.com/fyql/p/12362351.html

时间: 2024-10-04 13:22:37

[Java复习] 面试突击 - MySQL的相关文章

[Java复习] 面试突击 - Spring

说说你对Spring的IoC机制的理解? 没有Spring之前: 写一套系统,web服务器,tomcat,一旦启动之后,他就可以监听一个端口号的http请求,然后可以把请求转交给你的servlet,jsp,配合起来使用的,servlet处理请求. 比如在我们的一个tomcat + servlet的这样的一个系统里,有几十个地方,都是直接用MyService myService = new MyServiceImpl(),直接创建.引用和依赖了一个MyServiceImpl这样的一个类的对象. 这

java复习基础篇——Mysql数据库

数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作. mysql的dos窗口启动关闭命令:net start mysql和net stop mysql 登录命令:(1)mysql -u用户名 -p密码      (2)mysql --host=ip地址 --user=用户名 --password=密码 DOS操作数据乱码解决: 我们在dos命令行操作中文时,会报错ERROR 1366 (HY000): Inco

java复习汇总之面试篇

这些个人感觉都是基础,希望看的园友不要喷. 1.什么是servlet线程安全,如何解决? 2.spring事物管理,在项目中你是怎么管理事物的? 3.java中的有几种线程? 4.java有几种锁? 5.怎么理解java中的多态,项目中何时用到抽象类? 6.如何处理js,sql注入? 7.struts2拦截器的原理? 8.如何理解spring AOP? 11.java中常用的集合,在项目中用到时,有什么需要注意的? 12.如果优化项目中sql,为什么要那样优化? 13.java性能优化? 14.

放手一搏:社招Java岗面试经历(三年经验): PingCAP、蚂蚁

前言 今年想出来看看机会,最后很幸运地拿到了 PingCAP,今日头条的 offer 以及蚂蚁金服的口头 offer.想着可以总结一下经验,分享一下自己这一段"骑驴找马"过的心路历程.当然,一家之言,难免粗浅,如有不妥,敬请指正. 全文有点长,假如只对一家公司感兴趣的话可以直接跳过去: 准备过程 我自己是本科毕业后在老东家干了三年多,老东家算是一家"小公司"(毕竟这年头没有 BAT 或 TMD 的 title 都不好意思报出身),毕业这两年多我也没有在大厂待过,因此

[Java复习] 分布式高可用-Hystrix

什么是Hystrix? Hystrix 可以让我们在分布式系统中对服务间的调用进行控制,加入一些调用延迟或者依赖故障的容错机制. Hystrix 的设计原则 对依赖服务调用时出现的调用延迟和调用失败进行控制和容错保护. 在复杂的分布式系统中,阻止某一个依赖服务的故障在整个系统中蔓延.比如某一个服务故障了,导致其它服务也跟着故障. 提供 fail-fast(快速失败)和快速恢复的支持. 提供 fallback 优雅降级的支持. 支持近实时的监控.报警以及运维操作. Hystrix 更加细节的设计原

java运行代码连接mysql时提示:找不到类错误

使用IntelliJ IDEA Community Edition进行代码编写.. 使用一下代码连接mysql时出现了:java.lang.ClassNotFoundException: com.mysql.jdbc.Driver错误 然后就很好奇,import都能导入数据. 后来用idea工具打开以前的练习,发现架包也存在. 但是新建的练习就没有把架包弄进来.然后出现了这类错误.. 原因是:使用idea工具开发时,如果之前练习有添加相应的数据,那么在external libraries中是能显

java异常面试常见题目

在Java核心知识的面试中,你总能碰到关于 处理Exception和Error的面试题.Exception处理是Java应用开发中一个非常重要的方面,也是编写强健而稳定的Java程序的关键,这自然使它成为面试题中的常客.关于Java中Error和Exception的面试题目多是关于Exception和Error的概念,如何处理Exception,以及 处理Exception时需要遵守的最佳实践等等.尽管关于多线程.垃圾回收.JVM概念和面向对象设计等方面的问题依然主宰着这类面试,你仍然需要为回答

Java多线程面试15道

Java 线程面试问题 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题.在投资银行业务中多线程和并发是一个非常受欢迎的话题,特别是电子交易发展方面相关的.他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者有足够的Java线程与并发方面的知识,因为候选人中有很多只浮于表面.用于直接面向市场交易的高容量和低延时的电子交易系统在本质上是并发的.下面这些是我在不同时间不同地点喜欢问的Jav

java运行jdk连接mysql出现了:Establishing SSL connection without server&#39;s identity verification is not recommended

注意:出现这类提示也不会影响对数据库的增删改查操作,所以不用紧张.. 在运行练习时出现下面的错误信息提示: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if