1. SQL排查

1.1 慢查询日志: mysql提供的一种日志记录, 用户记录MySQL中响应时间超过阈值的SQL语句(long_query_time, 默认10秒), 慢查询日志默认是关闭的, 建议开发调优时打开, 最终部署的时候关闭

1.1.1 检查是否开启了慢查询日志

show variables like '%slow_query_log%';

临时开启:

set global slow_query_log = 1; -- 在内存中开启
exit;
service mysql restart

永久开启:

vim /etc/my.cnf -- 追加配置
[mysqld]
slow_query_log=1
slow_query_log_file=/var/lib/mysql/localhost-slow.log

1.1.2 慢查询阈值

show variables like '%long_query_time%'; -- 查看
-- 临时设置阈值
set global long_query_time = 3; 
永久设置阈值:
vim /etc/my.cnf 中追加配置 
[mysqld]
long_query_time=3-- 查询
select sleep(4);
select sleep(3);
-- 查询超过阈值的SQL
show global status like '%slow_queries%';
-- 慢查询的sql被记录在了日志中,因此可以通过日志查看具体的慢SQL
cat /data/mysql/zizhou-slow.log 

9.2 通过mysqldumpslow工具查看慢SQL,可以通过一些过滤条件,快速查找需要定位的慢SQL

mysqldumpslow --help
-- 获取返回记录最多的3个SQL
mysqldumpslow -s r -t 3 /data/mysql/zizhou-slow.log
-- 获取访问次数最多的3个SQL
mysqldumpslow -s c -t 3 /data/mysql/zizhou-slow.log
-- 按照时间排序, 前10条包含left join 查询语句的SQL
mysqldumpslow -s t -t 10 -g "left join" /data/mysql/zizhou-slow.log
-- 语法
mysqldumpslow 各种参数 慢查询日志的文件

mysqldumpslow命令的帮助:
在这里插入图片描述

2. 分析海量数据

2.1 模拟海量数据, 存储过程(无return)/存储函数(有return)

create database test_data;
use test_datacreate table dept(dno int(5) primary key default 0,dname varchar(20) not null default '',loc varchar(30) not null default ''
)engine=innodb default charset=utf8mb4;create table emp(eid int(5) primary key,ename varchar(20) not null default '',job varchar(20) not null default '',deptno int(5) not null default 0
)engine=innodb default charset=utf8mb4;

2.1.1 通过存储函数,插入海量数据

-- 创建存储函数
delimiter $ create function randstring(n int)   returns varchar(255) begindeclare  all_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ;declare return_str varchar(255) default '' ;declare i int default 0 ; while i<n		 do									set return_str = concat(  return_str,      substring(all_str,   FLOOR(1+rand()*52)   ,1)       );set i=i+1 ;end while ;return return_str;end $ delimiter $ create function ran_num() returns int(5)begindeclare i int default 0;set i =floor( rand()*100 ) ;return i ;end $

2.1.2 通过存储过程,插入海量数据

-- emp表
delimiter $ create procedure insert_emp( in eid_start int(10),in data_times int(10))begin declare i int default 0;set autocommit = 0 ;repeatinsert into emp values(eid_start + i, randstring(5) ,'other' ,ran_num()) ;set i=i+1 ;until i=data_timesend repeat ;commit ;end $-- dept表
delimiter $ create procedure insert_dept(in dno_start int(10) ,in data_times int(10))begindeclare i int default 0;set autocommit = 0 ;repeatinsert into dept values(dno_start+i ,randstring(6),randstring(8)) ;set i=i+1 ;until i=data_timesend repeat ;commit ;end$

2.1.3 插入数据

delimiter ; 
call insert_emp(1000,800000) ;
call insert_dept(10,30) ;

2.1.4 问题解决

如果报错: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable)
是因为存储过程/存储函数在创建时, 与之前开启的慢查询日志冲突了
解决冲突:

-- 临时解决(开启log_bin_trust_function_creators)
show variables like '%log_bin_trust_function_creators%';
set global log_bin_trust_function_creators = 1;-- 永久解决
vim /etc/my.cnf追加配置
[mysqld]
log_bin_trust_function_creators = 1

2.2 分析海量数据

2.2.1 profiles

show profiles; -- 默认关闭
show variables like '%profiling%';
set profiling = on;

show profiles 会记录profiling打开之后的全部SQL查询语句所花费的时间. 缺点: 不够精确,只能看到总共消费的时间,不能看到各个硬件消费的时间(cpu, io)

2.2.2 精确分析: sql诊断

show profile all for query 上一步查询的Query_id;
show profile cpu,block io for query 上一步查询的Query_id;

2.2.3 全局查询日志: 记录开启之后的全部SQL语句(这次全局的记录操作仅仅在于调优, 开发过程中打开即可, 在最终部署的时候一定要关闭)

show variables like '%general_log%';
-- 执行的所有SQL记录在表中
set global general_log = 1; -- 开启全局日志
set global log_output='table'; -- 设置将全部SQL记录在表中-- 执行的所有SQL记录在文件中
set global log_output='file';
set global general_log = on;
set global general_log_file='/tmp/general.log';
-- 开启后,会记录所有SQL : 会被记录 mysql.general_log表中。
select * from  mysql.general_log ;

3. 锁机制:解决因资源共享而造成的并发问题

例如: A和B同时买最后一件衣服X
A: X加锁 --> 试衣服 -->下单 --> 付款 --> 打包 --> 解锁
B: 发现X已被加锁, 等待X解锁, X已售空

3.1 分类

3.1.1 操作类型:

  1. 读锁(共享锁): 对同一个数据(衣服), 多个读操作可以同时进行, 互不干扰
  2. 写锁(互斥锁): 如果当前写操作没有完毕(买衣服的一系列操作), 则无法进行其他的读写操作

3.1.2 操作范围

  1. 表锁: 一次性对一张表整体加锁, 如MyISAM引擎使用表锁, 开销小, 加锁快; 无死锁, 但是锁的范围大, 容易发生锁冲突, 并发度低
  2. 行锁: 一次对一条数据加锁, 如InnoDB存储引擎使用行锁, 开销大, 加锁慢, 容易出现死锁; 锁的范围较小, 并发度高(很小概率发生高并发问题:脏读/幻读/不可重复读/丢失更新等问题)
  3. 页锁

3.2 表锁示例(MyISAM)

-- (1) 表锁: 自增操作,MYSQL/SQLSERVER支持;oracle需要借助于序列来实现自增
create table table_lock(id int primary key auto_increment,name varchar(20)
)engine=myisam;
insert into table_lock(name) values('a1');
insert into table_lock(name) values('a2');
insert into table_lock(name) values('a3');
insert into table_lock(name) values('a4');
insert into table_lock(name) values('a5');
commit;
-- 增加锁
lock table 表1 read/write,表2 read/write
-- 查看加锁的表
show open tables;

会话session: 每一个访问数据的dos命令行、数据库客户端工具,都是一个会话

-- 加读锁-- 会话0:lock table table_lock read;select * from table_lock; -- 读(查), 可以delete from table_lock where id = 1; -- 写,不可以select * from emp; -- 读,不可以delete from emp where id = 1; -- 写,不可以-- 结论1: 如果某一个会话对A表加了read锁, 则该会话可以对A表进行读操作,不能进行写操作;且该会话不能对其他表进行读,写操作; -- 即如果给A表加了读锁, 则当前会话只能对A表进行读操作-- 会话1(被锁的表):select * from table_lock;   --读(查),可以delete from table_lock where id =1 ; --写,会“等待”会话0将锁释放-- 会话1(其他表):select * from emp ;  --读(查),可以delete from emp where eno = 1; --写,可以-- 结论2:会话0给A表加了锁;其他会话的操作: a.可以对其他表(A表以外的表)进行读,写操作	b.对A表可以进行读操作, 但写操作需要等待锁释放unlock tables; -- 释放锁-- 读锁总结: 在当前会话只锁一张A表, 只能对A表进行读操作(写操作不行), 其他表不能进行读写操作.其他会话可以对A表进行读操作,写操作需要等会话0将锁释放,对其他表可以进行读写操作-- 加写锁-- 会话0:lock table table_lock write;-- 写锁总结: 在当前会话只锁一张A表, 可以对加锁的A表进行读写操作,但是不能对其他表进行读写操作.在其他会话, 要对加锁的A表进行增删改查的操作,需要等待当前会话将锁释放

2.2.1 MySQL表级锁的锁模式

MyISAM在执行查询语句(select)前, 会自动将涉及到的所有表加读锁, 在执行更新操作(DML)前, 会自动给涉及到的表加写锁, 所以对MyISAM表进行操作,会有以下情况:

  1. 对MyISAM表的读操作(加读锁), 不会阻塞其他进程(会话)对同一张表的读需求, 但会阻塞对同一张表的写需求, 只有当读锁释放后, 才能进行其他进程的写操作
  2. 对MyISAM表的写操作(加写锁), 会阻塞其他进程(会话)对同一张表的读写操作, 只有当写锁释放之后, 才会执行其他进程的读写操作

2.2.2 分析表锁定

-- 查看哪些表加了锁(1代表加了锁)
show open tables;
-- 分析表锁定的严重性
show status like 'table%';
-- Table_locks_immediate: 即可能获取到的锁数
-- Table_locks_waited: 需要等待的表锁数(该值越大, 说明存在越大的锁竞争)

一般建议:Table_locks_immediate/Table_locks_waited > 5000, 建议采用InnoDB引擎, 否则使用MyISAM引擎

2.3 行锁示例(InnoDB)

create table line_lock(id int(5) primary key auto_increment,name varchar(20)
) engine=innodb;
insert into line_lock(name) values('1');
insert into line_lock(name) values('2');
insert into line_lock(name) values('3');
insert into line_lock(name) values('4');
insert into line_lock(name) values('5');
-- mysql默认自动commit, oracle默认不会自动commit; 为了研究行锁, 暂时将自动commit关闭, 以后需要通过commit提交
set autocommit = 0;

2.3.1 操作同样的数据

-- 会话0:写操作
insert into line_lock value('a6');
-- 会话1:写操作同样的数据
update line_lock set name='ax' where id = 6;

结论:

  1. 如果会话对某条数据进行DML操作(研究时关闭了autocommit的情况下), 则其他会话必须等待会话X结束事务(commit/rollback)后, 才能对数据a进行操作
  2. 表锁是通过unlock tables, 也可以通过事务解锁, 行锁是通过事务解锁

2.3.2 操作不同的数据

-- 会话0:写操作
insert into line_lock value(8,'a8');
-- 会话1:写操作
update line_lock set name = 'ax3' where id = 5;

结论: 行锁,一次锁一行数据;因此, 如果操作的是不同数据, 则互不干扰

2.3.3 行锁的注意事项

1. 如果没有索引, 则行锁会转为表锁

show index from line_lock;
alter table line_lock add index idx_line_lock_name(name);-- 会话0:写操作
update line_lock set name = 'ai' where name = '3';
-- 会话1:写操作, 不同的数据
update line_lock set name = 'aix' where name = '4';-- 可以发现, 数据被阻塞了(加锁)
-- 原因:如果索引发生了类型转换, 则索引失效, 因此此次操作, 会从行锁转为表锁

2.行锁的一种特殊情况: 间隙锁, 值在范围内, 却不存在

-- 此时line_lock表中没有id=7的数据
update line_lock set name = 'X' where id > 1 and id < 9; -- 即在where范围中, 没有id=7的数据, 则id=7的数据成为间隙

间隙锁: mysql会自动给间隙加索引, 即本demo中会自动给id = 7的数据加间隙锁(行锁)
行锁: 如果没有where, 则实际加索引的范围就是where后面的范围, 不是实际的值

如果仅仅只是查询数据, 能否加锁? 可以! 通过for update对query语句进行加锁

set autocommit = 0;
start transaction;
begin;
select * from line_lock where id = 2 for update;

行锁: InnoDB默认采用行锁, 相较于表锁性能消耗较大, 但有着并发能力强,效率高的优势, 因此建议高并发用InnoDB,否则使用MyISAM
行锁分析:

show status like '%innodb_row_lock%';
-- Innodb_row_lock_current_waits: 当前正在等待锁的数量
-- Innodb_row_lock_time: 等待总时长,从系统启动到现在一共等待的时间
-- Innodb_row_lock_time_avg: 平均等待市场,从系统启动到现在平均等待的时间
-- Innodb_row_lock_time_max: 最大等待时长, 从系统启动到现在最大一次等待的时间
-- Innodb_row_lock_waits: 等待次数,从系统启动到现在一共等待的次数

本篇是对B站颜群老师SQL优化视频的笔记梳理, 感兴趣的可以去看下视频: SQL优化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916838.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916838.shtml
英文地址,请注明出处:http://en.pswp.cn/news/916838.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

conda 安装prokka教程

本章教程,记录如何在wsl2+ubuntu下载通过conda安装prokka软件包。 Prokka 是一个快速的、功能强大的基因组注释工具,特别适用于细菌基因组的注释。它能够自动化完成从基因组序列到功能注释的整个流程,包括基因的识别、功能预测和注释,并且支持多种文件格式输出,广泛应用于…

CSS3 圆角

CSS3 圆角 引言 CSS3圆角是现代网页设计中非常重要的一项功能&#xff0c;它使得网页元素的外观更加平滑、美观。本文将详细介绍CSS3圆角的概念、实现方法以及相关属性&#xff0c;帮助您更好地掌握这一技巧。 CSS3圆角概念 CSS3圆角指的是通过CSS3属性为元素&#xff08;如div…

牛顿-拉夫森法求解非线性方程组

牛顿-拉夫森法&#xff08;Newton-Raphson method&#xff09;是一种用于求解非线性方程组的迭代方法。该方法通过线性化非线性方程组&#xff0c;并逐步逼近方程组的解。以下是牛顿-拉夫森法求解非线性方程组的详细步骤和MATLAB实现。 1. 牛顿-拉夫森法的基本原理 对于非线性方…

Windows系统使用命令生成文件夹下项目目录树(文件结构树)的两种高效方法

Windows系统使用命令生成文件夹下项目目录树&#xff08;文件结构树&#xff09;的两种高效方法前言&#xff1a;**方法一&#xff1a;tree 命令 —— 快速生成经典目录树****方法二&#xff1a;PowerShell —— 可以精准过滤“降噪”的命令**这份列表非常精炼&#xff0c;只包…

react中暴露事件useImperativeHandle

注&#xff1a;本页面模块主要是使用 useImperativeHandle &#xff0c;一、概述1、要点hooks 中的暴露事情件方法useImperativeHandle&#xff0c;需要和forwardRef、ref 结合一起使用。1、外层校验的时候会校验里面所有需要校验的验证2、基础使用二、demo案例1、场景1、弹框打…

【论文阅读】-《RayS: A Ray Searching Method for Hard-label Adversarial Attack》

RayS&#xff1a;一种用于硬标签对抗攻击的光线搜索方法 Jinghui Chen University of California, Los Angeles jhchencs.ucla.edu Quanquan Gu University of California, Los Angeles qgucs.ucla.edu 原文链接&#xff1a;https://arxiv.org/pdf/2006.12792 摘要 深度神经…

15K的Go开发岗,坐标北京

好久没有分享最新的面经了&#xff0c;今天分享一下北京某公司Go开发岗的面经&#xff0c;薪资是15K左右&#xff0c;看看难度如何&#xff1a; 为什么要用分布式事务 分布式事务的核心作用是解决跨服务、跨数据源操作的数据一致性问题。在单体应用中&#xff0c;数据库本地事务…

Linux 文件管理高级操作:复制、移动与查找的深度探索

目录一、文件复制&#xff1a;从基础到企业级同步的全维度解析1. cp命令&#xff1a;基础工具的进阶密码&#xff08;1&#xff09;文件属性保留&#xff1a;从基础到极致&#xff08;2&#xff09;特殊文件处理&#xff1a;稀疏文件与设备文件&#xff08;3&#xff09;安全操…

Redis内存使用耗尽情况分析

目录 1、内存上限介绍 1.1、产生原因 1.2、Redis的maxmemory限额 1.3、影响的命令与场景 2. 内存用完后的策略 2.1、淘汰策略分类 2.2、淘汰策略介绍 2.3、不同策略对比 3、常见业务示例 3.1、影响 3.2、监控与自动告警 前言 在日常项目中&#xff0c;不知道你思考过…

Ubuntu 系统中配置 SSH 服务教程

一、什么是 SSH&#xff1f;SSH&#xff08;Secure Shell&#xff09;是一种加密的网络协议&#xff0c;用于在不安全的网络中安全地进行远程登录、远程命令执行和文件传输。它是 Telnet、FTP 等传统协议的安全替代品。二、确认系统环境在开始配置之前&#xff0c;请确认你的系…

基于springboot的编程训练系统设计与实现(源码+论文)

一、开发环境 技术/工具描述MYSQL数据库一个真正的多用户、多线程SQL数据库服务器&#xff0c;适用于Web站点或其他应用软件的数据库后端开发。B/S结构基于互联网系统的软件系统开发架构&#xff0c;利用浏览器进行访问&#xff0c;支持多平台使用。Spring Boot框架简化新Spri…

K8s集群两者不同的对外暴露服务的方式

在工作中&#xff0c;我们暴露集群内的服务通常有几种方式&#xff0c;对于普通的http或者https,我们通常使用​Ingress Nginx​ &#xff0c;对于原始的TCP或者UDP端口服务&#xff0c;可能需要选择 ​LoadBalancer​ &#xff0c;它们的核心区别在于工作层级、协议支持和流量…

实习日志111

第一天 加入内网和内网域&#xff0c;设置自己的操作系统 第二天 安装常用软件和平台 Notepad 是一款免费的源代码编辑器&#xff0c;支持多种编程语言&#xff0c;其功能强大且界面友好&#xff0c;适用于 Windows 操作系统。WinMerge 是一款开源的差异比较和合并工具&…

Redis 服务挂掉排查与解决

Redis 是一个高性能的键值对存储系统&#xff0c;广泛应用于缓存、会话存储、消息队列等场景。在使用 Redis 的过程中&#xff0c;偶尔会遇到 Redis 服务挂掉或无法连接的情况。本文将通过常见错误 RedisException in Redis.php line 63 Connection refused 来讲解如何排查并解…

DOM + HTML + HTTP

一、HTML5的新特性 1.语义化标签:其实就是可以让标签有自己的含义 html4之前都是有的,比如:<h1>、<ul>、<li> html5新增了很多语义化标签:<header>、<nav> html5的语义化标签的常用页面布局: 优点: 1.代码结构清晰,方便阅读,有利于团…

HTML 音频/视频

HTML 音频/视频 引言 HTML 音频和视频标签是网页设计中不可或缺的部分,它们为用户提供了一种将多媒体内容嵌入到网页中的方式。本文将详细介绍 HTML 音频/视频标签的用法、属性和注意事项,帮助开发者更好地在网页中嵌入音频和视频。 HTML 音频标签( ) 1. 标签基本用法 …

Apache Ignite Cluster Groups的介绍

以下这段内容是 Apache Ignite 官方文档中关于 Cluster Groups&#xff08;集群组&#xff09; 的介绍。我来用通俗易懂的方式帮你全面理解这个概念。&#x1f310; 什么是 Cluster Group&#xff1f; 简单来说&#xff1a;Cluster Group 就是一个“节点的子集”。想象一下你的…

github上传本地项目过程记录

最近有和别人进行unity项目协作的需求&#xff0c;需要把自己的本地代码上传到github已有的一个仓库里。记录一下上传过程&#xff0c;防止后续还需要用。 文章目录一、把自己的本地代码上传到github已有的一个仓库中二、常用功能一、把自己的本地代码上传到github已有的一个仓…

Spring AI Alibaba

目录 前言&#xff1a; 一、Spring AI 和Spring AI Alibaba 二、Spring AI Alibaba快速入门 1.环境 2.ollama 3.阿里百炼 前言&#xff1a; 2025年真的是AI大爆发的一年&#xff0c;以后无论是什么行业我想都需要AI了&#xff0c;作为一名计算机人&#xff0c;你不学习AI…

【GaussDB】内存资源告急:深度诊断一起“memory temporarily unavailable“故障

【GaussDB】诊断一起内存临时不可用的问题 &#x1f4cb; 背景 在客户测试环境中&#xff08;GaussDB 506.0 SPC0100 集中式&#xff09;&#xff0c;一个重度使用存储过程的系统&#xff0c;频繁出现内存临时不可用的问题(ERROR: memory is temporarily unavailable)。令人困…