mysql高级

SQL性能优化与MySQL实战
本文深入探讨SQL性能优化策略,涵盖分层架构、存储引擎、SQL执行流程、索引原理与优化技巧,以及MySQL查询分析与锁机制,提供详实的案例分析,助力数据库性能提升。

一.分层架构
1.连接层

在这里插入图片描述

2.服务层
在这里插入图片描述

3.引擎层
在这里插入图片描述
4.存储层
在这里插入图片描述

二.存储引擎
1.docker 安装mysql

命令:
docker ps -a 
docker start c_mysql
docker exec -it c_mysql /bin/bash

mysql查看存储引擎

show variables like '%engine%';

在这里插入图片描述
2.常见存储引擎

show engines;

在这里插入图片描述
在这里插入图片描述
三.SQL性能
1.性能下降的原因:
sql语句烂
索引失效
关联查询太多join
服务器调优及参数设置

2.sql执行加载顺序:
select 字段 from 表名1 left join 表名2 on 连接条件
where 条件 group by 分组 having 分组后的筛选条件
order by 排序条件 limit 起始,步长;

机读顺序:
在这里插入图片描述

3.7种join的编写

在这里插入图片描述

案例:

create table    `tbl_dept` (
    id int(11) not null  auto_increment,
                           deptName varchar(30) default  null,
                           locAdd varchar(40) default  null,
                           primary key (id)
)engine =INNODB AUTO_INCREMENT=1 DEFAULT  charset ='UTF8';

create table `tbl_emp`(
    id int(11) not null auto_increment,
    name varchar(20) default  null,
    deptId int(11) default null,
    primary key (id),
    key `fk_dept_id` (`deptId`)
   # constraint `fk_dept_id` foreign key (`deptId`) references tbl_dept(id)
 )engine =innodb auto_increment=1 default  charset ='utf8';

insert into tbl_dept (deptName, locAdd) values ('RD',11);
insert into tbl_dept (deptName, locAdd) values ('HR',12);
insert into tbl_dept (deptName, locAdd) values ('MK',13);
insert into tbl_dept (deptName, locAdd) values ('MIS',14);
insert into tbl_dept (deptName, locAdd) values ('FD',15);

insert into tbl_emp (name, deptId) values ('z3',1);
insert into tbl_emp (name, deptId) values ('z4',1);
insert into tbl_emp (name, deptId) values ('z5',1);

insert into tbl_emp (name, deptId) values ('w5',2);
insert into tbl_emp (name, deptId) values ('w6',2);

insert into tbl_emp (name, deptId) values ('s7',3);

insert into tbl_emp (name, deptId) values ('s8',4);

insert into tbl_emp (name, deptId) values ('s9',51);

7种join:

select * from tbl_emp inner join tbl_dept on tbl_emp.deptId=tbl_dept.id;

在这里插入图片描述

select * from tbl_emp left join tbl_dept on tbl_emp.deptId=tbl_dept.id;

在这里插入图片描述

select * from tbl_emp right join tbl_dept on tbl_emp.deptId=tbl_dept.id;

在这里插入图片描述

select * from tbl_emp left join  tbl_dept on tbl_emp.deptId=tbl_dept.id  where tbl_dept.id is null;

在这里插入图片描述

select * from tbl_emp right join  tbl_dept on tbl_emp.deptId=tbl_dept.id  where tbl_emp.id is null;

在这里插入图片描述

select * from tbl_emp left join  tbl_dept on tbl_emp.deptId=tbl_dept.id  union select * from tbl_emp right join  tbl_dept on tbl_emp.deptId=tbl_dept.id;

在这里插入图片描述

select * from tbl_emp left join  tbl_dept on tbl_emp.deptId=tbl_dept.id where tbl_dept.id is null union select * from tbl_emp right join  tbl_dept on tbl_emp.deptId=tbl_dept.id where tbl_emp.id is null ;

在这里插入图片描述

4.索引
本质为一种排好序的快速查找数据结构

一种可能的索引方式示例:
在这里插入图片描述
为了加速col2的查找,维护一个二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录的物理地址的指针,从而运用二叉查找在一定复杂度内获取相应数据。

注意:
a.逻辑删除
(保留数据,供数据分析使用;避免索引失效)
b.没有特别指明,一般使用B树索引

5.索引的优劣势
a.优势
类似于图书馆建立书目索引,提高数据检索的效率,降低数据库的io成本;
通过索引列对数据进行排序,降低数据排序的成本,降低cpu的消耗;

b.劣势

实际上索引也是一张表,保存主键和索引字段,并且指向实体表中的记录,所以索引列也占用空间
虽然索引大大提升了查询的效率,但是降低表的更新操作效率,因为更新表时,mysql不仅要保存数据,还要保留索引文件中每次更新添加了索引列的字段
索引是提高查询效率的一个因素,若存在大量的数据,则需要建立优秀的索引和sql查询语句

6.索引的分类和建索引的命令
a.分类
单值索引:一个索引仅包含单列,一个表可有多个单列索引
唯一索引:索引列的值必须唯一,且允许空值
复合索引:一个索引包含多个列

b.命令
创建索引:

create [unique]index 索引名称 on 表名(字段(长度));

注意:
若字段为char、varchar类型,长度可小于实际长度;
若字段为blob、text类型,则必须指定长度

alter 表名 add [unique] index [索引名称] on (字段(长度));

在这里插入图片描述
例:

create index idx_tbl_dept_id on tbl_dept(deptName);
show index from tbl_dept;

在这里插入图片描述
删除索引:

drop index [索引名称] on 表名;

查看索引:

show index  from 表名;

7.mysql索引结构
a. BTree索引
b. Hash索引
c. Full-text全文索引
d. R-Tree索引

重点:BTree索引
在这里插入图片描述
若查找数据项29,首先将磁盘块1由磁盘加载到内存,发生第一次IO,在内存中二分查找确定29在17到35之间,锁定p2指针,内存时间非常短暂忽略不计;其次将磁盘块2加载到内存,发生第二次IO,29介于26到30之间,锁定p2指针;最后将磁盘块8加载到内存,发生第三次IO,确定29的地址,查找结束。

7.索引运用场景
a.适合建立索引:
主键自动建立唯一索引;
频繁作为查询条件的字段建立索引;
查询与其他表关联的字段,外键关系建立索引;
where条件中用不到的字段不创建索引;
单值和复合索引的选择(高并发场景下使用复合索引);
查询中排序的字段若使用索引,速率大大提升;
查询中统计分组字段;

b.不适合建立索引:
表记录太少;
经常增删改的字段;(不但保存数据,还需要保存索引文件);
数据重复且分布平均的表字段,只为经常查询和排序的字段建立索引,
若包含大量重复数据,则建立索引没有实际效果;

注意:
索引的选择性,即列中不重复的记录 与总记录条数的比值,越接近于1,索引效率越高;

四.性能分析
1.mysql query optimizer
在这里插入图片描述

2.mysql常见瓶颈
a. cpu饱和 一般发生在数据装入内存中或者从磁盘读取数据时;
b. 磁盘io瓶颈一般发生在装入数据远大于内存容量时;
c. 服务器硬件性能瓶颈:top free iostat vmstat 查看

3.explain
a.简介:
使用explain关键字,模拟优化器执行sql语句
b.作用
表的读取顺序
数据读取操作的操作类型
哪些索引可以使用
哪些索引被使用
表之间的引用
每张表有多少行被优化器查询
c.操作
explain sql语句

explain  select * from tbl_dept;

在这里插入图片描述
详细说明:

id:

select查询的序列号,表示查询执行select子句或操作表的顺序;
存在三种情况:
id相同时,执行顺序由上到下;
在这里插入图片描述
id不相同时,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行;
在这里插入图片描述
id存在相同和不同时,id相同可视为一组,从上往下顺序执行,在所有组中,id值越大优先级越高,越先被执行
在这里插入图片描述
(derived2 虚拟表,id为2执行后形成)
select_type
类型:
simple:简单子查询,查询中不包含子查询或union;
primary:查询中包含任何复杂的子部分时,最外层为primary;
subquery:在select或where中包含了子查询;
derived:在from列表中,包含的子查询被标记为derived,mysql会递归执行这些子查询,形成临时表;
union:若第二个select出现在union之后,则被标记为union;
union result:从union表中获取结果的select;

explain select * from tbl_emp left join  tbl_dept on tbl_emp.deptId=tbl_dept.id union select * from tbl_emp right join  tbl_dept on tbl_emp.deptId=tbl_dept.id ;

在这里插入图片描述
table
关于哪张表

type
type显示访问类型,是一种较为重要的指标,结果值从最好到最坏排序:
system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>
index_subquery>range>index>All
主要参考:
system>const>eq_ref>ref>range>index>ALL
一般而言,查询至少达到range级别,最好到ref;

system:表只有一行记录,为const类型的特例,平时不会出现;

const:通过索引一次就找到,const用于比较primary key或unique索引。因为只匹配一行数据,所以很快。如将主键置于where条件列表中,mysql能将该查询转换为一个常量;

eq_ref:唯一性索引,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描
在这里插入图片描述

ref:非唯一索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,然而可能会找到多个符合条件的行,属于查找与扫描的混合;
在这里插入图片描述
range:只检索给定范围的行,使用一个索引来选择行。key显示使用了哪个索引。一般出现在where语句中使用between > < in查询。这种范围扫描索引扫描比全表扫描好;
在这里插入图片描述
index: full index scan;index和All的区别:index只遍历索引树,通常比ALL快,因为索引文件通常比数据文件小;
在这里插入图片描述
all: 遍历全表找到匹配的行
在这里插入图片描述
possible keys:
显示可能应用在这张表的索引,一个或多个;
查询涉及到的字段若存在索引,则被列出,但不一定实际运用到

key:
实际使用的索引,若为null,则没有使用索引
若查询中出现覆盖索引,则索引仅出现在key列表中,possible keys不显示;

key_len:
表示索引中使用的字节数,可通过该列计算查询中使用的索引长度,在不损失精度的情况下,长度越短越好。key_len 显示索引最大的可能长度,并非实际使用长度,即key_len是通过表定义计算而得,而不是表内检索出来的;

ref:
显示索引哪一列被使用了,如果可能的话,是一个常量。那些列或常量被用来查找索引列的值
在这里插入图片描述
rows:
根据表统计信息以及索引选用情况,大致估算出找出所需记录所需要读取的行数
在这里插入图片描述
Extra:
类型:
(重要的三个)
using filesort:
mysql对数据使用了一个外部的索引排序,而不是按照表内的索引顺序进行读取在这里插入图片描述

using temporary:
使用临时表保存中间结果,mysql在对查询结果排序时使用临时表,常见于order by 和group by
在这里插入图片描述

using index:
表示select操作中使用了覆盖索引,避免访问了表的数据行,
若同时出现using where,表明索引被用来执行索引键值的查找,
若没有出现using where,表明索引被用来读取数据而不是执行查找动作;
在这里插入图片描述
(了解)
using where:
表明使用了where过滤

using join buffer:
使用连接缓存

impossible where:
表明where子句为false,不能获取任何元组

select tables optimized away:
在没有group by子句的情况下 ,基于索引优化min/max操作
或者 对于myisam存储引擎优化count(*)操作,不必等到执行阶段再进行计算
查询执行计划生成的阶段即完成了优化

distinct
优化distinct,在找到第一匹配的元组后即停止查找相同值的工作;

案例:
在这里插入图片描述
在这里插入图片描述
4.索引优化
左外连接时,左边一定均有,则在右表建立索引;右外连接时,右边一定均有,则在左表建立索引;
join优化:使用小结果集驱动大结果集;
优先优化内层;
保证被驱动表的条件字段被索引;
无法保证被驱动表的条件字段被索引且资源充足,不吝啬joinBuffer设置

案例
sql语句:

create table staffs(
    id int primary key  auto_increment,
    name varchar(24) not null  default  '' comment '姓名',
    age  int not null  default 0 comment '年龄',
    pos varchar(20) not null default '' comment '职位',
    add_time timestamp  not null  default  current_timestamp comment '入职时间'
) charset utf8 comment '职工表';
insert into staffs (name, age, pos, add_time) values ('z3',22,'manager',now());
insert into staffs (name, age, pos, add_time) values ('yt',21,'dev',now());
insert into staffs (name, age, pos, add_time) values ('ytru',21,'dev',now());
select * from staffs;
alter table staffs add index idx_staffs_nameAgePos (name,age,pos);

规则:
a.全值匹配我最爱
有效:

explain select * from staffs where  name='z3';

在这里插入图片描述

explain select * from staffs where  name='z3'and age=22;

在这里插入图片描述

explain select * from staffs where  name='z3'and age=22 and pos='manager';

在这里插入图片描述
无效:

explain select * from staffs where   age=22 and pos='manager';

在这里插入图片描述
b.最佳左前缀法则:
从索引的最左前列开始且不能跳过中间的列
explain select * from staffs where name=‘z3’ and pos=‘manager’;
在这里插入图片描述
(跳过了age列,ref仅出现单个const)

explain select name,age,pos from staffs where  name='z3' and pos='manager'  and age=20;

在这里插入图片描述
(mysql进行了优化操作)
c.不在索引列上做任何操作(计算、函数、自动手动类型转换),会导致索引的失效而转向全表扫描:
explain select * from staffs where left(name,2)=‘z3’;
在这里插入图片描述

d.存储引擎中不能使用索引中条件范围右边的列

explain select * from staffs where  name='z3' and age=22 and pos='manager';

在这里插入图片描述

explain select * from staffs where  name='z3' and age>20 and pos='manager';

在这里插入图片描述
**e.尽量使用覆盖索引(只访问索引的查询),减少select ***

desc staffs;

在这里插入图片描述

explain select * from staffs where  name='z3' and age=22 and pos='manager';

在这里插入图片描述

explain select name,age,pos from staffs where  name='z3' and age=22 and pos='manager';

在这里插入图片描述

explain select name,age,pos from staffs where  name='z3' and age>20 and pos='manager';

在这里插入图片描述
f.mysql在使用不等于(!= 或> <)的时候无法使用索引会导致全表扫描

explain select * from staffs where  name!='z3';

在这里插入图片描述

explain select * from staffs where  name<>'z3';

在这里插入图片描述
g.is null 或is not null 无法使用索引

explain select * from staffs where  name is null;

在这里插入图片描述

explain select * from staffs where  name is not null;

在这里插入图片描述
h.like 关键字以通配符开头,mysql索引失效,全表扫描

explain select * from staffs where  name like '%z3%';

在这里插入图片描述

通配符放置在左边:

explain select * from staffs where  name like 'z3%';

在这里插入图片描述
解决 like ‘%字符串%’ 索引不被使用的方法:
可以使用主键索引
使用覆盖索引,查询字段必须是建立覆盖索引字段
当覆盖索引指向的字段是varchar(380)及380以上的字段时,覆盖索引会失效!

i.字符串不加单引号会使索引失效

explain select * from staffs where  name = '2000';

在这里插入图片描述

explain select * from staffs where  name = 2000;

在这里插入图片描述
j.少用or关键字,用or连接时会索引失效

explain select * from staffs where  name='z3' or name='2000';

在这里插入图片描述
在这里插入图片描述

口诀:
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
like百分写最右,覆盖索引不写星;
不等空值还有or,索引失效要少用;
var引号不可丢,sql高级也不难;

五.查询截取分析

查询优化;
慢查询的开启并捕获;
explain+慢sql分析;
show profile 查询sql在mysql服务器中的执行细节和生命周期情况;
sql数据库服务器的参数调优;

1.查询优化:
a.小表驱动大表
在这里插入图片描述
in与exists:

select 字段列表 from  表名 where exists (子查询);

exists 关键字表示将主查询的数据,放入子查询中做条件验证,并根据子查询的结果来决定是否保留主查询中的数据;

b.order by关键字优化
order by 关键字尽量使用index方式排序,避免使用FillSort方式排序;
在这里插入图片描述
在这里插入图片描述
mysql支持两种排序方式,fileSort和index,index效率高;
order by使用index方式排序的情况:order by使用索引最左前列,where子句和order by子句条件组合满足索引最左前列

若不在索引列上,fileSort有两种算法:
双路排序:
mysql4.1之前使用双路排序,两次扫描磁盘,最终得到数据。读取行指针和order by列,对其进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据输出;
单路排序:
取一次数据,扫描磁盘两次,磁盘io很耗时,因此在mysql4.1之后,出现单路排序;从磁盘中读取查询需要的所有列,按照order by列在buffer对其进行排序,然后扫描排序后的列表进行输出。效率高,避免了第二次扫描,并且把随机io变成顺序io,但需要更多的空间,因为其将每一行都保存在内存中
单路总体而言,优于双路,但是存在问题:
在这里插入图片描述
优化的策略:
增加sort_buffer_size参数设置;
增加max_length_for_sort_data参数的设置;

总结:
mysql的两种排序方式:文件排序和扫描有序索引排序;
mysql能为查询和排序使用相同的索引
在这里插入图片描述

c.group by关键字优化
group by实质是先排序后分组,遵照左前缀原则;
无法使用索引列时,增加sort_buffer_size参数设置,增加max_length_for_sort_data参数的设置;
where高于having,能在where中限定的条件,不去having限定;

d.mysql慢查询日志
含义:
mysql提供的一种日志记录,用来记录响应时间超过阈值的sql语句,具体指响应时间超过long_query_time的sql,则会被记录到慢查询日志中;然后结合explain全面分析;

开启:
默认情况下,mysql没有开启慢查询日志,手动设置;
若不是调优需要,不建议开启,影响性能;
查看是否开启

show variables like '%slow_query_log%';

在这里插入图片描述

set global slow_query_log =1;

在这里插入图片描述
(了解,永久生效)
在这里插入图片描述
slow_query_log =1
slow_query_log_file =/var/lib/mysql/chen-slow.log
在这里插入图片描述

使用:

a.开启后记录到慢查询日志中的sql语句:
受参数long_query_time控制,默认为10秒

show variables like ‘%long_query_time%’;
在这里插入图片描述
注意:在mysql源码中是判断大于long_query_time,而不是大于等于;

b.设置慢的阈值:

set global long_query_time =3;
show variables  like '%long_query_time%';

在这里插入图片描述
注意:
设置后看不到修改,解决方法:
重新连接或新开一个会话;

show variables like 'long_query_time';

在这里插入图片描述
或者

   show global variables like  '%long_query_time%';

在这里插入图片描述
c.

   select sleep(4);

d.查询系统有多少条慢查询记录

show global  status like '%Slow_queries%';

日志分析工具mysqldumpshow:
(1).mysqldumpshow帮助信息
在这里插入图片描述
(2).常用参考
在这里插入图片描述
e.批量插入数据脚本
范例:插入1000万条数据

(1)建表

create database if not exists bigData;
use bigData;
create table dept(
    id int unsigned primary key auto_increment,/*unsigned 无符号*/
    deptno mediumint unsigned not null default 0,
    dname varchar(20) not null default '',
    loc varchar(13) not null default ''
)engine =innodb default charset =GBK;
create table emp(
    id int unsigned primary key  auto_increment,
    empno mediumint unsigned not null  default 0,/*编号*/
    ename varchar(20) not null default '',/*姓名*/
    job varchar(9) not null default '',/*工作*/
    mgr mediumint unsigned not null default 0,/*上级编号*/
    hiredate date not null ,/*入职时间*/
    sal decimal(7,2) not null ,/*薪水*/
    comm decimal(7,2) not null ,/*红利*/
    deptno mediumint unsigned not null default 0/*部门编号*/

)engine =innodb default charset =gbk;

(2)设置参数log_bin_trust_function_creators
由于开启过慢日志,开启了bin-log

show variables  like '%log_bin_trust_function_creators%';

在这里插入图片描述

set global  log_bin_trust_function_creators=1;
show variables  like '%log_bin_trust_function_creators%';

在这里插入图片描述
(3)创建函数保证每条数据不一样

delimiter $$
create function rand_string (n int) returns varchar(255)
begin
    declare chars_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(chars_str,floor(1+rand()*52),1));
     set i=i+1;
     end while ;
     return return_str;
end $$
show create function rand_string;

在这里插入图片描述

delimiter $$
create function rand_num() returns  int(5)
begin
    declare i int default 0;
    set i=floor(100+rand()*10);
    return i;
end $$
show create function rand_num;

在这里插入图片描述
(4)创建存储过程

delimiter $$
create procedure insert_emp (in start int(10),in max_num int(10))
begin
    declare i int default 0;
    set autocommit =0; /*开启事务*/
    start transaction ;
    repeat
        set i=i+1;
        insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno) values ((start+1),rand_string(6),'salesman',0001,curdate(),2000,400,rand_num());
    until i=max_num
        end repeat ;
    commit ;
end $$
show create procedure  insert_emp;
show create procedure  insert_emp;

在这里插入图片描述

delimiter $$
create procedure  insert_dept (in start int(10),in max_num int(10))
begin
    declare i int default 0;
    set autocommit =0;
    repeat
        set i=i+1;
        insert into  dept (deptno, dname, loc) values ((start+1),rand_string(10),rand_string(8));
    until i=max_num
    end repeat ;
    commit;
end $$
show create procedure insert_dept;

在这里插入图片描述

(5)调用存储过程

delimiter ;
call insert_dept(100,10);

在这里插入图片描述

delimiter ;
call insert_emp(100001,500000);

在这里插入图片描述

f.Show Profile
(1)含义:
mysql提供用来分析当前会话中语句执行的资源消耗情况;
默认情况下,参数处于关闭状态,保存最近15次的sql运行结果
(2)分析步骤:
查看当前版本是否支持:

show variables like '%profiling%';

在这里插入图片描述

默认情况下为关闭状态,打开

set profiling =on;
show variables like '%profiling%';

在这里插入图片描述

运行sql

select * from emp e inner  join  dept  d on e.deptno=d.id;

select * from emp group by  id%10 limit 150000;
select * from emp group by  id%20  order by 5;

查看结果

show profiles ;

在这里插入图片描述

诊断sql:

show profile  cpu,block io  for query 150;

在这里插入图片描述
参数备注:
在这里插入图片描述
日常开发中注意:
converting heap to ismyam,查询结果太大,内存不够,往磁盘上搬了;
creating tmp table 创建了临时表;
copying to tmp table on disk 把内存中的临时表复制到磁盘中,危险;
locked

g.全局日志查询
禁止在生产环境中启用;

启用:
在这里插入图片描述

编码开启:

set global  general_log =1;
set global log_output ='TABLE';	
SELECT * FROM mysql.general_log;

在这里插入图片描述
六.mysql锁机制

1.概述

a.定义:
锁是计算机协调多个进程或线程并发访问某一资源的机制;

b.锁的分类:
按数据操作类型划分:
读锁(共享锁):针对同一份数据,多个读操作可同时进行,且不会相互影响
写锁(排他锁):当且写操作没完成之前,阻断写锁和读锁
按数据操作粒度划分:
行锁
表锁

2.表锁
a.定义:
偏向于MYISAM存储引擎,开销小,加锁快,无死锁,,锁定粒度大,发生锁冲突的概率最高,并发最低;

b.案例:

create table if not exists mylock(
    id int   primary key  auto_increment,
    name varchar(20)
)engine myisam;

insert into mylock(name) values ('a');
insert into mylock(name) values ('b');
insert into mylock(name) values ('c');
insert into mylock(name) values ('d');
insert into mylock(name) values ('e');

select * from mylock;
手动增加表锁:    
  lock tables 表名 read(write),表名 read(write);
查看加锁的表:
show open tables;
释放表锁:
unlock tables
show open tables;

在这里插入图片描述

lock tables mylock read,emp write ;
show open tables;

在这里插入图片描述

unlock tables ;
show open tables ;

在这里插入图片描述

加读锁
会话1中:

lock tables mylock read ;
select * from mylock;

在这里插入图片描述

update mylock set name='a2' where id =1;

在这里插入图片描述

select * from emp;

在这里插入图片描述

会话2中:

select * from mylock;

在这里插入图片描述

update mylock set name='a3' where id =1;  #形成阻塞

在这里插入图片描述

会话一

unlock tables ;

会话2(阻塞解除)
在这里插入图片描述

总结:
当前session不能读取其他没有锁定的表,其他session可读取更新没有锁定的表;当前session插入或更新锁定的表,会提示错误,其他session插入或更新锁定的表,会处于阻塞状态;当前session释放锁,其他session插入或更新完成

加写锁:
会话1:

lock tables mylock write ;
select * from mylock;
update mylock set name='a4' where id =1;

在这里插入图片描述

select * from emp;

在这里插入图片描述

会话2:

select * from mylock; #阻塞

在这里插入图片描述

总结:
当前session对表的查询、更新、插入操作均可执行,其他session对表的查询阻塞,等待锁的释放
在这里插入图片描述

c.表锁分析:
查看哪些加锁表

show open tables;

分析表锁定

show status  like 'table_locks%';

在这里插入图片描述
在这里插入图片描述

myisam的读写锁调度是写优先,写锁后,其他线程不能做任何操作,形成阻塞

3.行锁
a.定义:
偏向innodb存储引擎,开销大,加锁慢,会出现死锁;锁定粒度小,发生锁冲突的概率最低,并发度最高

b.案例

create table if not exists test_innodb_lock (
    a int(11),
    b varchar(16)
)engine =innodb;
insert into test_innodb_lock values (1,'b2');
insert into test_innodb_lock values (2,'3');
insert into test_innodb_lock values (3,'4000');
insert into test_innodb_lock values (4,'5000');
insert into test_innodb_lock values (5,'6000');
insert into test_innodb_lock values (6,'7000');
insert into test_innodb_lock values (7,'8000');
insert into test_innodb_lock values (8,'9000');
insert into test_innodb_lock values (9,'bfd');
insert into test_innodb_lock values (1,'b1');
create index test_innodb_lock_a_idx  on test_innodb_lock(a);
create index test_innodb_lock_b_idx on test_innodb_lock(b);
select * from test_innodb_lock;

在这里插入图片描述

会话1:

set autocommit =0;

会话2:

set autocommit =0;

会话1:

update test_innodb_lock set b='b2233' where a=1;
select * from test_innodb_lock;

在这里插入图片描述
会话2

select * from mylock;

在这里插入图片描述
会话1

commit ;

会话2

commit ;
select * from mylock;

在这里插入图片描述

行锁阻塞其他会话的更新操作:
会话1

update test_innodb_lock set b='33' where a=2;

会话2

update test_innodb_lock set b='39903' where a=2;

在这里插入图片描述

注意:
CAP理论
一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)
(1)满足CA舍弃P,也就是满足一致性和可用性,舍弃容错性。但是这也就意味着你的系统不是分布式的了,因为涉及分布式的想法就是把功能分开,部署到不同的机器上。

(2)满足CP舍弃A,也就是满足一致性和容错性,舍弃可用性。如果你的系统允许有段时间的访问失效等问题,这个是可以满足的。就好比多个人并发买票,后台网络出现故障,你买的时候系统就崩溃了。

(3)满足AP舍弃C,也就是满足可用性和容错性,舍弃一致性。这也就是意味着你的系统在并发访问的时候可能会出现数据不一致的情况。

c.无索引行锁变为表锁

varchar 不用 ’ ’ 导致系统自动转换类型, 行锁变表锁

d.间隙锁
在这里插入图片描述
e.锁定一行的操作
在这里插入图片描述

f.总结
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七.主从复制
1.主从复制基本原理
slave会从master读取binlog进行数据的同步
在这里插入图片描述
mysql复制过程分为三步:
master将改变记录到二进制日志(binary log).这些记录过程叫做二进制日志时间,binary log events;
slave将master的binary log events 拷贝到它的中继日志(relay log);
slave重做中继日志中的时间,将改变应用到自己的数据库中。mysql复制是异步且串行化的

2.主从复制基本原则
每个slave只有一个master
每个slave只能有一个唯一的服务器id
每个master可以有多个slave

3.主从复制最大问题
延时

4.主从复制步骤(Windows 和linux)
a.查看ip,ping两台机器,保持mysql版本一致
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

但行益事莫问前程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值