系列文章目录
- 2024年java面试(一)–spring篇
- 2024年java面试(二)–spring篇
- 2024年java面试(三)–spring篇
- 2024年java面试(四)–spring篇
- 2024年java面试–集合篇
- 2024年java面试–redis(1)
- 2024年java面试–redis(2)
文章目录
MySQL有哪些锁
基于粒度:
- 表级锁:对整张表加锁,粒度大并发小
- 行级锁:对行加锁,粒度小并发大
- 间隙锁:间隙锁,锁住表的一个区间,间隙锁之间不会冲突只在可重复读下才生效,解决了幻读
基于属性:
- 共享锁:又称读锁,一个事务为表加了读锁,其它事务只能加读锁,不能加写锁
- 排他锁:又称写锁,一个事务加写锁之后,其他事务不能再加任何锁,避免脏读问题
$和#
#占位符的特点
- MyBatis处理 #{ } 占位符,使用的 JDBC 对象是PreparedStatement 对象,执行sql语句的效率更高。
- 使用PreparedStatement 对象,能够避免 sql 注入,使得sql语句的执行更加安全。
- #{ } 常常作为列值使用,位于sql语句中等号的右侧;#{ } 位置的值与数据类型是相关的。
$占位符的特点
- MyBatis处理 ${ } 占位符,使用的 JDBC 对象是 Statement 对象,执行sql语句的效率相对于 #{ } 占位符要更低。
- ${ } 占位符的值,使用的是字符串连接的方式,有 sql 注入的风险,同时也存在代码安全的问题。
- ${ } 占位符中的数据是原模原样的,不会区分数据类型。
- 占位符常用作表名或列名,这里推荐在能保证数据安全的情况下使用{ } 占位符常用作表名或列名,这里推荐在能保证数据安全的情况下使用 占位符常用作表名或列名,这里推荐在能保证数据安全的情况下使用{ }。
数据库三范式具体是什么
第—范式:每个列都不可以再拆分。
第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分。
第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。
Mysql内连接、左连接、右连接的区别
内连接取量表交集部分,左连接取左表全部右表匹部分,右连接取右表全部坐表匹部分
where和having的区别?
where是约束声明,having是过滤声明,where早于having执行,并且where不可以使用聚合函数,having可以
char和varchar的区别
char是不可变的,最大长度为255,varchar是可变的字符串,最大长度为2^16
InnoDB 什么情况下会产生死锁
事务1已经获取数据A的写锁,想要去获取数据B的写锁,然后事务2获取了B的写锁,想要去获取A的写锁,相互等待形成死锁。 mysql解决死锁的机制有两个:1.等待, 直到超时 2.发起死锁检测,主动回滚一条事务 死锁检测的原理是构建一个以事务为顶点、 锁为边的有向图, 判断有向图是否存在环, 存在即有死锁。
MySQL 删除自增 id,随后重启 MySQL 服务,再插入数据,自增 id 会从几开始?
innodb 引擎:
MySQL8.0前,下次自增会取表中最大 id + 1。原理是最大id会记录在内存中,重启之后会重新读取表中最大的id
MySQL8.0后,仍从删除数据 id 后算起。原理是它将最大id记录在redolog里了
myisam:
自增的 id 都从删除数据 id 后算起。原理是它将最大id记录到数据文件里了
MySQL插入百万级的数据如何优化?
(1)一次sql插入多条数据,可以减少写redolog日志和binlog日志的io次数(sql是有长度限制的,但可以调整)
(2)保证数据按照索引进行有序插入
(3)可以分表后多线程插入
Mybatis 中一级缓存与二级缓存
1.MyBatis的缓存分为一级缓存和 二级缓存。
一级缓存是SqlSession级别的缓存,默认开启。
二级缓存是NameSpace级别(Mapper)的缓存,多个SqlSession可以共享,使用时需要进行配置开启。
2.缓存的查找顺序:二级缓存 => 一级缓存 => 数据库
简述Mybatis的动态SQL,列出常用的6个标签及作用
动态SQL是MyBatis的强大特性之一 基于功能强大的OGNL表达式。
动态SQL主要是来解决查询条件不确定的情况,在程序运行期间,根据提交的条件动态的完成查询
常用的标签:
<if> : 进行条件的判断
<where>:在<if>判断后的SQL语句前面添加WHERE关键字,并处理SQL语句开始位置的AND 或者OR的问题
<trim>:可以在SQL语句前后进行添加指定字符 或者去掉指定字符.
<set>: 主要用于修改操作时出现的逗号问题
<choose> <when> <otherwise>:类似于java中的switch语句.在所有的条件中选择其一
<foreach>:迭代操作,批量操作
Select 语句完整的执行顺序
(1)from 子句组装来自不同数据源的数据;
(2)where 子句基于指定的条件对记录行进行筛选;
(3)group by 子句将数据划分为多个分组;
(4)使用聚集函数进行计算;
(5)使用 having 子句筛选分组;
(6)计算所有的表达式;
(7)select 的字段;
(8)使用order by 对结果集进行排序。
如何保证接口的幂等性
-
根据状态机很多时候业务表是有状态的,比如订单表中有:1-下单、2-已支付、3-完成、4-撤销等状态。如果这些状态的值是有规律的,按照业务节点正好是从小到大,我们就能通过它来保证接口的幂等性。假如id=123的订单状态是已支付,现在要变成完成状态。update order set status=3 where id=123 and status=2;第一次请求时,该订单的状态是已支付,值是2,所以该update语句可以正常更新数据,sql执行结果的影响行数是1,订单状态变成了3。后面有相同的请求过来,再执行相同的sql时,由于订单状态变成了3,再用status=2作为条件,无法查询出需要更新的数据,所以最终sql执行结果的影响行数是0,即不会真正的更新数据。但为了保证接口幂等性,影响行数是0时,接口也可以直接返回成功。
具体步骤:
1 用户通过浏览器发起请求,服务端收集数据。
2 根据id和当前状态作为条件,更新成下一个状态
3 判断操作影响行数,如果影响了1行,说明当前操作成功,可以进行其他数据操作。
4 如果影响了0行,说明是重复请求,直接返回成功。 -
获取token
除了上述方案之外,还有最后一种使用token的方案。该方案跟之前的所有方案都有点不一样,需要两次请求才能完成一次业务操作。
第一次请求获取token
第二次请求带着这个token,完成业务操作。
具体步骤:
1 用户访问页面时,浏览器自动发起获取token请求。
2 服务端生成token,保存到redis中,然后返回给浏览器。
3 用户通过浏览器发起请求时,携带该token。
4 在redis中查询该token是否存在,如果不存在,说明是第一次请求,做则后续的数据操作。
5 如果存在,说明是重复请求,则直接返回成功。
6 在redis中token会在过期时间之后,被自动删除。