基础
SQL语句
select * from user limit m, n:跳过前m行,返回接下来的n行
SQL分析
sql前面加explain关键字,主要观察rows、type、key
- rows:查询时所扫描的行数
- type:查找数据行时使用的方法,
All全表扫描,range在索引树中定位到某个范围,index扫描整棵索引树 - key:如果用到了索引 则显示对应的索引名称,没有用索引显示NULL
索引失效
- 索引字段使用了关键字
like且以%开头 - 使用了联合索引但不符合最左前缀匹配
- 使用
is null或者is not null - 使用
!=操作符或者关键字or使用不当 - 索引中进行了运算或函数:
select name, age from user where age + 1 = 18
最左匹配原则
假设字段 (a,b,c) 建立联合索引,仅以a开头的查询能用到索引(跳过 a 直接查 b/c 索引完全失效),索引失效并不意味着需要回表,如果要查询的字段都在索引树中就不会回表了
b>1、b>=1、c>1、b>1 and c>1:索引无效a>=1 and b=1:a b都有效(b是等值匹配)a>=1 and b>1:a有效,b无效(b全局无序)
深分页处理
-
让查询条件都在索引树中,子查询只读索引树,外层查询利用子查询得到的id 快速定位数据
-
比如:
select * from table where name = 'yupi' limit 9999990, 10可以优化为:select * from table where id >= (select id from table where name = 'yupi' limit 9999990,1) and name = 'yupi' order by id limit 10
事务
隔离级别
- 读未提交:允许事务读取尚未提交的数据,可能产生脏读、不可重复读、幻读
- 读已提交:仅允许读取已经提交的数据,可能产生不可重复读、幻读
- 可重复读:确保同一事务内的多次读取结果一致
- 串行化
MVCC机制
-
简单来说就是select语句在执行前会生成一个 “历史事务id记录快照”,读取的时候 读已经提交的事务id 修改后的记录值。“可重复读“ 隔离级别下使用的是同一快照,所以不会看到其他事务的操作,就当其他事务没有操作过;”读已提交“ 隔离级别下,每次读取都是基于最新的“事务id记录快照”,可能会读取到 之前其他事务已经修改的数据
-
MVCC机制只存在于 “可重复读” 和 “读已提交” 两种事务隔离级别下
事务失效
-
自己捕获了异常
-
事务方法需要是
public修饰的 -
发生了内部调用,一个没有
@Transactional修饰的方法去调用了其他方法,解决方案:// 方式一:获取当前类的代理对象 UserService self = applicationContext.getBean(UserService.class);// 方式二:自己注入自己 public class UserService { @Autowried private UserService userService; }
故障排查
如何排查故障
-
杀死某个事务:
kill trx_mysql_thread_id -
查看客户端连接信息:
show processlist,查出来的id即为线程的id -
查看正在执行中的事务:
select * from information_schema.innodb_trx -
查看正在运行的锁信息:
select * from information_schema.innodb_locks
如何查看慢SQL
-
设置慢sql的阈值:
set global long_query_time = 3,3表示3秒 -
查询是否开启日志以及日志存储路径:
show variables like 'slow_query_log%' -
查看超过多长时间会记录日志:
show variables like 'long_query_time'
如何避免内存溢出
- 使用分页查询
- 避免一次加载大量字段
Mybatis
相关文章
sql练习题:sql语句练习50题(含解析)_sql练习-CSDN博客