线程崩溃、Java三大器、Sql慢查询

1.线程崩溃为什么不会引起JVM崩溃?

原文地址:美团一面:为什么线程崩溃不会导致JVM崩溃

线程非法操作或访问内存会导致进程崩溃(进程下的多个线程共享代码段,文件,数据,内存等)
那进程是如何崩溃的? -信号量机制
kill pid -9 就是向目标进程发送了一个信号量 SIGKILL-对应9
如果自定义了信号量函数,可以再kill掉进程之前执行一些自定义方法
jvm正是自定义了信号量函数,如发生NPE或者stackoverflow时,JMV做了额外的内部处理,并将日志写入特定文件比如hs_err.log中

2.Java三大器 

1.过滤器(基于函数回调):一般用于资源访问权限控制(比如部分静态资源请求可以过滤不做验证)、敏感词汇过滤

2.拦截器(基于java反射机制,动态代理):实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter方法
应用:用户登录认证、权限验证等

过滤器与拦截器、切面执行顺序验证
-> 过滤器doFilter -> 前置拦截器preHandle
-> 环绕通知@Around开始 -> 前置通知@Before
-> UserController
-> 环绕通知@Around执行 ->环绕通知@Around结束
-> 后置通知@After -> 后置返回通知@AfterReturning
-> 处理拦截器postHandle -> 后置拦截器afterCompletion


3.监听器(基于事件):依赖于servletContextListener接口或HttpSessionListener抽象依赖接口
应用场景:清除过期session、统计网站在线人数

区别:
1.在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时调用一次。
2.拦截器是基于java反射机制来实现的,而过滤器是基于函数回调来实现的。

 3.数据库慢查询原因  转载地址:盘点数据库慢查询的12个原因_倾听铃的声的博客-CSDN博客_慢查询

第一类SQL写法原因原因:

1.没有用到索引(隐式类型转换、使用or、使用< >等符号、未遵守索引最左匹配原则、使用“%”开头的like通配符、索引列上使用内置聚合函数(加上聚合函数会导致mysql不知道如何搜索)、对索引列使用运算符号 +-*\ (和使用聚合函数同理)、左右连接的字符编码不一致),或者字段未创建索引

第二类MySql数据库原因:

1.被表锁、行锁锁住了

2.limit深分页问题 

例子:

select id,name,balance from account where create_time> '2020-09-19' limit 100000,10;

上述语句中limit 10000,10执行步骤:首先通过create_time索引字段查询到id后回表查询得到100010个数据后抛弃前10000行去最后10行。

limit深分页,导致SQL变慢原因有两个:

        limit语句会先扫描offset+n行,然后再丢弃掉前offset行,返回后n行数据。也就是说limit      100000,10,就会扫描100010行,而limit 0,10,只扫描10行。


        limit 100000,10 扫描更多的行数,也意味着回表更多的次数。

解决办法:延迟关联法(就是把条件转移到主键索引,减少回表。)

select  acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.create_time > '2020-09-19' limit 100000, 10) AS acct2 on acct1.id= acct2.id;

3.数据量过大,B+树过深,读取较多次数IO,影响效率

4.刷新脏页 

更新语句执行步骤

 

rodo_log:

 

更新语句暂时更新到内存和redo log中,等数据库空闲时再更新到磁盘里,因此会出现脏页(内存和数据库数据不一致)。如果内存不够用,或者redo_log满了,导致数据库刷新脏页(刷新脏页时导致查询和更新性能降低)

扩展:为什么要二阶段提交(将redo_log分成两阶段,一个prepare和commit阶段,中间穿插着写入binglog日志操作)?

未使用二阶段提交,先写redo_log后写binglog:比如数据库在写redo_log日志时crash了,没有及时写入binglog,此时数据库恢复时redo_log会记录保存这个修改,而后续使用binglog备份或者恢复临时库时,这次更新修改不会记录下来,这样就出现了脏数据。

二阶段提交:写redo_log prepare状态->写入binglog日志->写入 redo_log commit状态,此时写入binglog后crash了,数据库恢复时由于不是commit状态,不保存修改,这样后续使用binglog日志恢复时不会出现脏数据。

4.order by 文件排序(一般利用到sort_buffer, 首先找到无序结果集,单独将排序的字段和主键放入缓存,进行排序,后回表取出结果集)

rowid排序:当数据行超过排序缓存字段最大值时

全字段排序:和rowid相比,无需排序后的回表(因为未超过排序字段允许的最大值,所以不需要单独对排序字段进行排序)

且sort_buffer_size过小会借助磁盘进行排序

优化方案就是使用合适的sort_buffer_size和max_sort_data字段大小,或者对排序字段建立索引等加快排序速度

5.group by 临时表

group by执行步骤: 创建临时表->取出分组字段并统计,对分组字段进行排序(此时参照上面的order by排序步骤,有可能走rowid排序,有可能走全字段排序)->取结果集

注意group by有会进行排序

解决方案,1.后加 order by null 指定不排序

                  2.对group by利用索引字段,即可不用临时表(索引是有序的,可以顺序读取或统计)

 

3.(比较少见):查询数据行有巨量的历史回滚版本,需要一致性读(可以增加读锁,当前读)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值