2021年Java中高级面试必备知识点总结
在这个部分总结了2019年到目前为止Java常见面试问题,取其面试核心编写成这份文档笔记,从中分析面试官的心理,摸清面试官的“套路”,可以说搞定90%以上的Java中高级面试没一点难度。
本节总结的内容涵盖了:消息队列、Redis缓存、分库分表、读写分离、设计高并发系统、分布式系统、高可用系统、SpringCloud微服务架构等一系列互联网主流高级技术的知识点。
目录:
(上述只是一个整体目录大纲,每个点里面都有如下所示的详细内容,从面试问题——分析面试官心理——剖析面试题——完美解答的一个过程)
部分内容:
对于每一个做技术的来说,学习是不能停止的,小编把2019年到目前为止Java的核心知识提炼出来了,无论你现在是处于什么阶段,如你所见,这份文档的内容无论是对于你找面试工作还是提升技术广度深度都是完美的。
不想被后浪淘汰的话,赶紧搞起来吧,高清完整版一共是888页,需要的话可以点赞+关注
MySQL是一种开源的关系型数据库管理系统,它使用SQL作为其查询语言。MySQL是最流行的开源数据库之一,它具有高性能、可靠性和可扩展性。MySQL支持多用户、多线程和多表操作,可以在各种操作系统上运行。
MySQL最为最流行的开源数据库,其重要性不言而喻,也是大多数程序员接触的第一款数据库,深入认识和理解MySQL也比较重要。
本篇博客分析MySQL的两种引擎,MyISAM和InnoDB引擎的区别。
本系列文章合集如下:
【合集】MySQL的入门进阶强化——从 普通人 到 超级赛亚人 的 华丽转身
目录
引出
1.MyISAM
只有表级锁,而InnoDB
支持行级锁和表级锁,默认为行级锁;
2.MyISAM
不提供事务支持。而InnoDB
提供事务支持;
3.MyISAM
不支持外键,而InnoDB
支持;
4.MyISAM
不支持聚集索引,InnoDB
支持聚集索引;
5MyISAM
不支持MVCC,InnoDB
支持。应对高并发事务,MVCC比单纯的加锁更高效;
特性 | InnoDB | MyISAM |
---|---|---|
事务安全 | 支持 | 无 |
存储限制 | 64TB | 有 |
空间使用 | 高 | 低 |
内存使用 | 高 | 低 |
插入数据的速度 | 低 | 高 |
对外键的支持 | 支持 | 无 |
1.是否支持行级锁
MyISAM
只有表级锁,而InnoDB
支持行级锁和表级锁,默认为行级锁。
(1)MySQL大致可以归纳为以下3种锁
- 表级锁:开销小,加锁快;不会出现死锁;锁的粒度大,发生锁冲突的概率最高,并发度最低。
- 行级锁:开销大,加锁慢;会出现死锁;锁的粒度小,发生锁冲突的概率最低,并发度最高。
- 页面锁:开销 和加锁时间界于表锁和行锁之间;会出现死锁,锁定的粒度界于表锁和行锁之间,并发一般。
(2)表锁
MyISAM会在执行select语句前,会自动给涉及的表加读锁,在执行增删改操作前会自动给涉及的表加写锁。
- MySQL的表锁有两种模式:
- 表共享读锁
- 表独占写锁
- 读锁会阻塞写,写锁会阻塞读和写。
- 对MyISAM表的读操作,不会阻塞其它进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它线程的写操作。
- 对MyISAM表的写操作,会阻塞其它进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。
读锁的演示
窗口1执行
窗口2的语句被阻塞
关闭窗口1,窗口2才执行成功
执行unlock tables释放锁
释放后才成功
create table dept(
deptno int not null auto\_increment,
dname varchar(20),
loc varchar(20),
primary key(deptno)
)ENGINE=MyISAM AUTO\_INCREMENT=1 DEFAULT CHARSET=utf8
# 打开两个会话窗口
# 窗口1执行以下语句
lock table dept read;
select \* from dept;
# 窗口2执行执行以下语句
select \* from dept;
insert into dept values(null,'财务部','北京');
# 此时,窗口2的请求被阻塞,必须等待会话1释放锁后才能执行;
# 释放会话1的锁,并观察会话2的执行结果。
unlock tables;
写锁的演示
会话1加写锁,会话2读操作,会被阻塞
会话1 释放锁
# 会话1加写锁
lock table dept write;
delete from dept where deptno = 1;
# 会话2读操作,会被阻塞
select \* from dept;
# 会话1 释放锁
unlock tables;
# 观察会话2 查询结果
注意:如果持有表锁的session异常终止的话(比如说执行了“ctrl+z”),那么该session是不会主动释放锁的,这时候我们可以重启mysql服务器,不推荐。可以通过show processlist 命令来查看线程ID,通过kill 【线程ID】
总结:MyISAM不适合写表的引擎,写锁后,其它线程不能做任何操作。
(3)行锁
会出现死锁,发生锁冲突几率低,并发高。
- MySQL的行锁是通过索引加载的,也就是说,行锁是加在索引选择的行上的,如果SQL语句没有走索引,则会进行全表扫描,行锁则无法实现,取而代之的是表锁;此时其它事物无法对当前表进行更新操作。
- 如果使用的是非主键索引,则行锁转为表锁。
新建一张表
插入两条数据
会话1的事务未提交,由于不是同一行,所以会话2
# 会话1 ,执行update,事务未提交。
start transaction;
update mylock set name = 'hello' where id = 1;
# 会话2 ,执行update,由于是通过主键更新,为行级锁;
#会话1和会话2更新的不是同一行数据,会话2可以执行成功
update mylock set name = 'world' where id = 2;
# 会话2 ,执行下面update语句,则会进行阻塞,
# 必须等待会话1提交事物释放锁。
update mylock set name = 'test' where id = 1;
上述案例的代码
create table mylock(
id int not null auto\_increment,
name varchar(20),
update_time datetime,
primary key(id)
)engine=innodb default charset=utf8
# 会话1 ,执行update,事务未提交。
start transaction;
update mylock set name = 'hello' where id = 1;
# 会话2 ,执行update,由于是通过主键更新,为行级锁;
# 会话1和会话2更新的不是同一行数据,会话2可以执行成功。
update mylock set name = 'world' where id = 2;
# 会话2 ,执行下面update语句,则会进行阻塞,
# 必须等待会话1提交事物释放锁。
update mylock set name = 'test' where id = 1;
会话1执行commit之后,绘画2事务才能执行
# 会话1 ,执行update,事务未提交,
# 由于通过非主键或索引选中的,升级为表锁。
start transaction;
update mylock set update_time ='2000-10-1' where name='hello'
commit
# 会话2,无法执行写操作,必须等待会话1的事务提交。
update mylock set name='abc' where id = 1;
显示加行锁的两种方式,行锁又分为共享锁和排他锁。
- 共享锁(乐观锁|S锁):允许不同事务之间共享加锁读取,但不允许其他事务修改或者加入排他锁
select * from user where id=20 lock in share mode
- 排他锁(悲观锁|X锁):当一个事务加入排他锁后,不允许其他事务加共享锁或排他锁读取
select * from user where id= 20 for update
- 行锁的前提有两个:1、必须是mysql的innoDb表。2、必须开启transaction事务。两者都有,锁才会生效。
- 若一个线程for update执行锁住某行数据,其他线程读取的时候,sql里没有for update,则可以正常读取。
如果是修改,则会被阻塞
只有会话1执行commit之后,会话2的update才成功
# 会话1 ,开启事物执行如下sql,事务未提交,开启读锁
start transaction;
select \* from mylock where id=1 lock in share mode;
# 会话2 ,允许读操作
select \* from mylock where id=1;
# 会话2,执行update写操作被阻塞,
# 必须等待会话1的事物提交释放锁。
update mylock set name = 'test' where id =1;
# 会话1,开启事务,执行如下sql,事务未提交,开启写锁
start transaction;
select \* from mylock where id=1 for update;
# 会话2,执行读和写操作,会发生阻塞
select \* from mylock where id=1 for update;
update mylock set name='test' where id=1;
(4)产生死锁
- 表锁不会产生死锁
- 在Innodb中,行级锁并不是直接锁记录,而是锁索引。
- 索引分为主键索引和非主键索引两种,如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引。
- 如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。
创建一个发生死锁的情景,在Session A
和Session B
中分别执行两个事务,具体情况如下:
MySQL 中事务的开始语句为 START TRANSACTION 或 BEGIN。这两个语句的效果是相同的,都可以用来开始一个新的事务。
时间编号 | SessionA | SessionB |
---|---|---|
1 | BEGIN; | |
2 | BEGIN; | |
3 | SELECT * FROM mylock where id = 1 FOR UPDATE | |
4 | SELECT * FROM mylock where id = 2 FOR UPDATE | |
5 | SELECT * FROM mylock where id =2 FOR UPDATE 发生阻塞 | |
6 | SELECT * FROM mylock WHERE id = 1 FOR UPDATE ; 死锁发生,纪录日志,回滚一个事物 |
死锁产生,会回滚事务
总结
在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了
2b47.png)
死锁产生,会回滚事务
总结
在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了
[外链图片转存中…(img-s8B0ASBG-1714867630928)]
[外链图片转存中…(img-DzPSdrju-1714867630929)]