MySQL基础知识

核心SQL

SQL主要可以划分为以下 3 个类别:

  • DDL(Data Definition Languages)语句
    数据定义语言,这些语句定义了不同的数据库、表、列、索引等数据库对象的定义。常用的语句关
    键字主要包括 create、drop、alter等。
  • DML(Data Manipulation Language)语句
    数据操纵语句,用于添加、删除、更新和查询数据库记录,并检查数据完整性,常用的语句关键字
    主要包括 insert、delete、update 和select 等。
  • DCL(Data Control Language)语句
    数据控制语句,用于控制不同的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户
    的访问权限和安全级别。主要的语句关键字包括 grant、revoke 等。

库操作

# 查询数据库
show databases;
# 创建数据库
create database ChatDB;
# 删除数据库
drop database ChatDB;
选择数据库
use ChatDB;

表操作

# 查看表
show tables;
#创建表
create table user(id int unsigned primary key not null auto_increment,
name varchar(50) not null,
age tinyint not null,
sex enum('M','W') not null)engine=INNODB default charset=utf8;
#查看表结构
desc user;
#查看建表sql
show create table user\G
#删除表(慎用)
drop table user;
CRUD
#insert插入一个数据,在表面后面加上value对应的字段,自增的id,当删除之后,再插入,不会复用之前的id
#使用第二个方法更快,因为只需要与MySQL Server进行一次连接,一个连接需要先进行TCP三次握手,而使用第一种插入两个value时需要两次连接
#因此使用一个连接池非常合适
insert into user(nickname, name, age, sex) values('fixbug', 'zhang san', 22,'M');
insert into user(nickname, name, age, sex) values('666', 'li si', 21, 'W'),('888', 'gao yang', 20, 'M');

#update
update user set age=23 where name='zhang san';
update user set age=age+1 where id=3;

#delete
delete from user where age=23;
delete from user where age between 20 and 22;
delete from user; #删除表所有数据

#select
select * from user;
select id,nickname,name,age,sex from user;
select id,name from user;
select id,nickname,name,age,sex from user where sex='M' and age>=20 and age<=25;
select id,nickname,name,age,sex from user where sex='M' and age between 20 and25;
select id,nickname,name,age,sex from user where sex='W' or age>=22;

#去重 distinct
select distinct name from user; 

#合并查询,相当于做两个查询,然后结果进行合并
SELECT expression1, expression2, ... expression_n
FROM tables[WHERE conditions]
UNION [ALL | DISTINCT] # 注意:union默认去重,不用修饰distinct,all表示显示所有重复值
SELECT expression1, expression2, ... expression_n
FROM tables[WHERE conditions]

SELECT country FROM Websites UNION ALL SELECT country FROM apps ORDER BY
country;

#分页,第一个数字是偏移量,后面是查询个数,如果只有一个数字,默认偏移量为0,使用第三种比第二种效率更高,选择一个有索引的字段,使用前一页的最大字段代替偏移量
select id,nickname,name,age,sex from user limit 10;
select id,nickname,name,age,sex from user limit 2000,10;
select id,nickname,name,age,sex from user where id >20000 limit 10;


#explain 查看MySQL执行计划
explain select id,nickname,name,age,sex from user where sex='M' and age>=20 and age<=25;

  • 当字段没有索引,而且数据我们只需要一行,加上limit 1,性能提升很多,因为不加的话,sql会查询整表,加上之后查到一行就不会继续向下查了
    在这里插入图片描述
#排序
select id,nickname,name,age,sex from user where sex='M' and age>=20 and age<=25 order by age asc;
select id,nickname,name,age,sex from user where sex='M' and age>=20 and age<=25 order by age desc;
#分组group by,会自动排序,因此group by使用带索引的字段,效率更高
select sex from user group by sex;
select count(id),sex from user group by sex;
select count(id),age from user group by age having age>20; #对于group的结果进行过滤使用having
多表查询

连接查询

  1. 内连接查询
  2. 外连接查询
    • left连接查询
    • right连接查询
      在这里插入图片描述
内连接

查询两个表的并集

# SELECT a.属性名1,a.属性名2,...,b,属性名1,b.属性名2... FROM table_name1 a inner join table_name2 b on a.id = b.id where a.属性名 满足某些条件;



#on a.uid= c.uid 根据数据量区分大表和小表,小表整表扫描,然后去大表里面搜索
#从student表中取出所有uid,然后去大表中搜索,因此大表建索引合适
#使用from后第一个出现的表连接之后的表,因此出现的第一个表需要能连接其他的表
SELECT a.uid,a.name,a.age,a.sex,c.score from student a 
INNER JOIN exame c ON a.uid = c.uid 
WHERE a.uid = 2;

#三表查询
SELECT a.uid,a.name,a.age,a.sex,c.score,b.cname from exame c 
INNER JOIN student a ON a.uid = c.uid 
INNER JOIN course b ON c.cid = b.cid
WHERE a.uid = 2;
外连接

// 把left这边的表所有的数据显示出来,在右表中不存在相应数据,则显示NULL
SELECT a.属性名列表, b.属性名列表 FROM table_name1 a LEFT [OUTER] JOIN table_name2 b on
a.id = b.id;

// 把right这边的表所有的数据显示出来,在左表中不存在相应数据,则显示NULL
SELECT a.属性名列表, b.属性名列表 FROM table_name1 a RIGHT [OUTER] JOIN table_name2 b on
a.id = b.id;

#外连接的条件过滤应该写在on后面,2,3句的效果相同
SELECT a.* ,b.cid from student a LEFT JOIN exame b ON a.uid=b.uid and b.cid=3 ;

SELECT a.* ,b.cid from student a LEFT JOIN exame b ON a.uid=b.uid WHERE b.cid=3 ;

SELECT a.* ,b.cid from student a  JOIN exame b ON a.uid=b.uid WHERE b.cid=3 ;

MySQL存储引擎

  • MyISAM数据和索引分开存储 不支持事务、也不支持外键,索引采用非聚集索引,其优势是访问的速度快,对事务完整性没有要求,以 SELECT、INSERT 为主的应用基本上都可以使用这个存储引擎来创建表。MyISAM的表在磁盘上存储成 3 个文件,其文件名都和表名相同,扩展名分别是:
    .frm(存储表定义)
    .MYD(MYData,存储数据)
    .MYI (MYIndex,存储索引)
  • InnoDB 数据和索引存储在一起存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全,支持自动增长列,外键等功能,索引采用聚集索引,索引和数据存储在同一个文件,所以InnoDB的表在磁盘上有两个文件,其文件名都和表名相同,扩展名分别是:
    .frm(存储表的定义)
    .ibd(存储数据和索引)
  • MEMORY 存储引擎使用存在内存中的内容来创建表。每个MEMORY 表实际只对应一个磁盘文件,格式
    是.frm(表结构定义)。MEMORY 类型的表访问非常快,因为它的数据是放在内存中的,并且默认使
    用 HASH 索引(不适合做范围查询),但是一旦服务关闭,表中的数据就会丢失掉。

MySQL索引

索引是创建在表上的,是对数据库表中一列或者多列的值进行排序的一种结果。索引的核心是提高查询
的速度!
物理上(聚集索引&非聚集索引)

  • 聚集索引对应主键索引
  • 非聚集索引对应普通索引

索引的优点: 提高查询效率
索引的缺点: 索引并非越多越好,过多的索引会导致CPU使用率居高不下,由于数据的改变,会造成索
引文件的改动,过多的磁盘I/O造成CPU负荷太重

  1. 普通索引:没有任何限制条件,可以给任何类型的字段创建普通索引(创建新表&已创建表,数量是不限的,一张表的一次sql查询只能用一个索引 where a=1 and b=‘M’)
  2. 唯一性索引:使用UNIQUE修饰的字段,值不能够重复,主键索引就隶属于唯一性索引
  3. 主键索引:使用Primary Key修饰的字段会自动创建索引(MyISAM, InnoDB)
  4. 单列索引:在一个字段上创建索引
  5. 多列索引:在表的多个字段上创建索引 (uid+cid,多列索引必须使用到第一个列,才能用到多列索引,否则索引用不上)
  6. 全文索引:使用FULLTEXT参数可以设置全文索引,只支持CHAR,VARCHAR和TEXT类型的字段上,常用于数据量较大的字符串类型上,可以提高查询速度(线上项目支持专门的搜索功能,给后台服务器增加专门的搜索引擎支持快速高效的搜索 elasticsearch 简称es C++开源的搜索引擎 搜狗的workflow)
#建表的时候创建索引
CREATE TABLE index1(id INT,
name VARCHAR(20),
sex ENUM('male', 'female'),
INDEX(id,name));
#添加索引
CREATE [UNIQUE] INDEX 索引名 ON 表名(属性名(length) [ASC | DESC]);
#删除索引
DROP INDEX 索引名 ON 表名;
  1. 经常作为where条件过滤的字段考虑添加索引
  2. 字符串列创建索引时,尽量规定索引的长度,而不能让索引值的长度key_len过长
  3. 索引字段涉及类型强转、mysql函数调用、表达式计算等,索引就用不上了
  4. 通过explain + mysql语句查看索引是否失效
索引的数据结构

B+树(InnoDB,MyISAM)
在这里插入图片描述

  • Innodb是聚集索引,其中B+树的非叶子节点存储key,叶子节点存储数据(主键索引存储的是完整的数据,普通索引存储索引列和主键列)
  • MyISAM中,数据和索引分开存储,是非聚集索引,因此索引的B+树中存放key和数据的磁盘地址
  1. B-树的每一个节点,存了关键字和对应的数据地址,而B+树的非叶子节点只存关键字,不存数据
    地址。因此B+树的每一个非叶子节点存储的关键字是远远多于B-树的,B+树的叶子节点存放关键
    字和数据,因此,从树的高度上来说,B+树的高度要小于B-树,使用的磁盘I/O次数少,因此查询
    会更快一些。
  2. B-树由于每个节点都存储关键字和数据,因此离根节点进的数据,查询的就快,离根节点远的数
    据,查询的就慢;B+树所有的数据都存在叶子节点上,因此在B+树上搜索关键字,找到对应数据
    的时间是比较平均的,没有快慢之分。
  3. 在B-树上如果做区间查找,遍历的节点是非常多的;B+树所有叶子节点被连接成了有序链表结
    构,因此做整表遍历和区间查找是非常容易的。
  4. 哈希索引当然是由哈希表实现的,哈希表对数据并不排序,因此不适合做区间查找,前缀查找,order by排序操作,效率非常低,需要搜索整个哈希表结构。哈希索引只有等值比较能达到O(1),memory存储引擎是使用的哈希索引,基于内存的存储引擎
  5. InnoDB自适应哈希索引,当一个普通索引不断被使用,就会根据二级索引在内存上构建一个哈希索引,
优化

查看慢查询日志(slow_query_log),可以设置一个时长(slow_query_time),当sql语句耗时超过这个时长,会记录在日志中,注意慢查询日志的开关是全局变量

全局变量意思是修改之后,每个会话都会受到影响,非全局的变量只跟单独的会话相关,其他会话不受影响

MySQL事务

一个事务是由一条或者多条对数据库操作的SQL语句所组成的一个不可分割的单元,只有当事务中的所
有操作都正常执行完了,整个事务才会被提交给数据库;如果有部分事务处理失败,那么事务就要回退
到最初的状态,因此,事务要么全部执行成功,要么全部失败(原子态),MyISAM不支持事务,InnoDB支持事务

例如账户转账的事务,A账户-500,T,B账户+500,在T时刻程序异常了,这肯定不可以。如果T时刻出错,整个事务需要回滚rollback,恢复到事务开始前状态。只有事务完整执行才会提交commit

所以记住事务的几个基本概念,如下:
1、事务是一组SQL语句的执行,要么全部成功,要么全部失败,不能出现部分成功,部分失败的结
果。保证事务执行的原子操作。
2、事务的所有SQL语句全部执行成功,才能提交(commit)事务,把结果写回磁盘上。
3、事务执行过程中,有的SQL出现错误,那么事务必须要回滚(rollback)到最初的状态。

当涉及事务时
首先 set autocommit=0;

BEGIN; 开启一个事务
COMMIT; 提交一个事务
ROLLBACK; 回滚一个事务到初始的位置
SAVEPOINT point1; 设置一个名字为point1的保存点
ROLLBACK TO point1; 事务回滚到保存点point1,而不是回滚到初始状态
SET TX_ISOLATION=‘REPEATABLE-READ’; 设置事务的隔离级别
SELECT @@ TX_ISOLATION; 查询事务的隔离级别 (mysql 5.
SELECT @@transaction_isolation;查询事务的隔离级别 (mysql 8.

ACID特性
每一个事务必须满足下面的4个特性:

  1. 事务的原子性(Atomic):
    事务是一个不可分割的整体,事务必须具有原子特性,及当数据修改时,要么全执行,要么全不执行,
    即不允许事务部分的完成。
  2. 事务的一致性(Consistency):
    一个事务执行之前和执行之后,数据库数据必须保持一致性状态。数据库的一致性状态必须由用户来负
    责,由并发控制机制实现。系统从一个正确的状态,迁移到另一个正确的状态。缓存和数据库的一致性
  3. 事务的隔离性(Isolation):
    当两个或者多个事务并发执行时,为了保证数据的安全性,将一个事务内部的操作与其它事务的操作隔
    离起来,不被其它正在执行的事务所看到,使得并发执行的各个事务之间不能互相影响。
  4. 事务的持久性(Durability):
    事务完成(commit)以后,DBMS保证它对数据库中的数据的修改是永久性的,即使数据库因为故障出
    错,也应该能够恢复数据!

原子性-undo log,
持久性-redo log
隔离性由锁机制(MVCC)实现
以上三条实现 一致性

隔离性
事务并发的问题

脏读(Dirty Read):一个事务读取了另一个事务未提交的数据。例如当事务A和事务B并发执行时,当事务A更新后,事务B查询读取到A尚未提交的数据,此时事务A回滚,则事务B读到的数据就是无效的脏数据。(事务B读取了事务A尚未提交的数据)必须杜绝
不可重复读(NonRepeatable Read):一个事务的操作导致另一个事务前后两次读取到不同的数据。例如当事务A和事务B并发执行时,当事务B查询读取数据后,事务A更新操作更改事务B查询到的数据,此时事务B再次去读该数据,发现前后两次读的数据不一样。(事务B读取了事务A已提交的数据)不是必须杜绝
虚读(Phantom Read)幻读:一个事务的操作导致另一个事务前后两次查询的结果数据量不同。例如当事务A和事务B并发执行时,当事务B查询读取数据后,事务A新增或者删除了一条满足事务B查询条件的记录,此时事务B再去查询,发现查询到前一次不存在的记录,或者前一次查询的一些记录不见了。(事务B读取了事务A新增加的数据或者读不到事务A删除的数据)不是必须杜绝

事务的隔离级别

MySQL支持的四种隔离级别是:
1、TRANSACTION_READ_UNCOMMITTED。未提交读。说明在提交前一个事务可以看到另一个事务的变化。这样读脏数据,不可重复读和虚读都是被允许的。
2、TRANSACTION_READ_COMMITTED。已提交读。说明读取未提交的数据是不允许的。这个级别仍然允许不可重复读和虚读产生。
3、TRANSACTION_REPEATABLE_READ。可重复读。说明事务保证能够再次读取相同的数据而不会失败,但虚读仍然会出现。
4、TRANSACTION_SERIALIZABLE。串行化。是最高的事务级别,它防止读脏数据,不可重复读和虚读。

在这里插入图片描述
备注:
事务隔离级别越高,为避免冲突所花费的性能也就越多。
在“可重复读”级别,实际上可以解决部分的虚读问题,但是不能防止update更新产生的虚读问题,要禁止虚读产生,还是需要设置串行化隔离级别。
通常工作在TRANSACTION_READ_COMMITTED 或者TRANSACTION_REPEATABLE_READ,主要就是是否允许不可重复读

事务隔离级别实现原理:

表级锁:对整张表加锁。开销小,加锁快,不会出现死锁;锁粒度大,发生锁冲突的概率高,并发度低。
行级锁:对某行记录加锁。开销大,加锁慢,会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度高。

排它锁(Exclusive),又称为X 锁,写锁。
共享锁(Shared),又称为S 锁,读锁。
X和S锁之间有以下的关系: SS可以兼容的,XS、SX、XX之间是互斥的
一个事务对数据对象 O 加了 S 锁,可以对 O 进行读取操作但不能进行更新操作。加锁期间其它事务能对O 加 S 锁但不能加 X 锁。
一个事务对数据对象 O 加了 X 锁,就可以对 O 进行读取和更新。加锁期间其它事务不能对 O 加任何锁。
显示加锁:select … lock in share mode强制获取共享锁,select … for update获取排它锁

InnnoDB的行锁是加在索引项(主键索引,普通索引都可以)上,而不是直接在行上,因此当过滤条件列没有索引时,使用的就是表锁

意向锁:意向共享锁(IS)意向排他锁(IX),出现的目的是,当一个事务获取表锁(X or S)时,需要先看此表有没有其他事务获取过行锁(X or S),若一条条数据扫描太慢。因此当有事务想获取行锁(X or S)时,需要先获取意向锁(IX or IS),意向锁都是表级锁,且意向锁之间不发生冲突
在这里插入图片描述

InnoDB行级锁

行级锁
InnoDB存储引擎支持事务处理,表支持行级锁定,并发能力更好。

1、InnoDB行锁是通过给索引上的索引项加锁来实现的,而不是给表的行记录加锁实现的,这就意味着
只有通过索引条件检索数据,InnoDB才使用行级锁,否则InnoDB将使用表锁。
2、由于InnoDB的行锁实现是针对索引字段添加的锁,不是针对行记录加的锁,因此虽然访问的是
InnoDB引擎下表的不同行,但是如果使用相同的索引字段作为过滤条件,依然会发生锁冲突,只能串
行进行,不能并发进行。
3、即使SQL中使用了索引,但是经过MySQL的优化器后,如果认为全表扫描比使用索引效率更高,此
时会放弃使用索引,因此也不会使用行锁,而是使用表锁,比如对一些很小的表,MySQL就不会去使用
索引。

间隙锁(共享锁) 实现串行化,完全解决幻读
当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB 会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)” ,InnoDB 也会对
这个“间隙”加锁,这种锁机制就是所谓的间隙锁。举例来说, 假如 user 表中只有 101 条记录, 其userid 的值分别是 1,2,…,100,101, 下面的 SQL:
select * from user where userid > 100 for update;
是一个范围条件的检索,InnoDB 不仅会对符合条件的 userid 值为 101 的记录加锁,也会对userid 大于 101(但是这些记录并不存在)的"间隙"加锁,防止其它事务在表的末尾增加数据。
InnoDB使用间隙锁的目的,为了防止幻读,以满足串行化隔离级别的要求,对于上面的例子,要是不使用间隙锁,如果其他事务插入了 userid 大于 100 的任何记录,那么本事务如果再次执行上述语句,就会发生幻读。

当使用的是主键或者唯一键的索引进行等值查询时,就没有间隙锁,如果是辅助索引,那就也有间隙锁,此时行锁+间隙锁=next-key luck
例子一
以下图为例子,事务二搜索id>11的数据,此时就会在id =12,22,23加行锁,并在(11,12](12,22](22,23],(23,+无穷]加间隙锁,此时想在间隙锁范围内插入就会阻塞。
在这里插入图片描述
例子二
当使用age的辅助索引时,搜索age>20的数据,间隙锁如下图的实线方框所示,在age=20和21之间也有间隙锁(读锁),因此插入age=20的数据,也会阻塞,拿不到排他锁(写锁)。
注意:当不使用索引时,是直接加表锁的
在这里插入图片描述

锁的优化建议

当发生阻塞,超过阻塞超时时间,事务就会回滚,因此尽量不要发生死锁
1.尽量使用较低的隔离级别
2.设计合理的索引并尽量使用索引访问数据,使加锁更加准确,减少锁冲突的机会提高并发能力
3.选择合理的事务大小,小事务发生锁冲突的概率小
4.不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序
存取表中的行。这样可以大大减少死锁的机会
5.尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响
6.不要申请超过实际需要的锁级别
7.除非必须,查询时不要显示加锁

MVCC多版本并发控制 实现已提交读和可重复读

已提交读和可重复读=》底层实现原理MVCC(多版本并发控制)=》并发的读取方式:快照读
Innodb提供了两个读取操作:锁定读―和非锁定读MVCC提供的快照读 =》依赖底层的一个技术=》undo log回滚日志

事务日志: undo log回滚日志 redo log重做日志
ACID四个特性 ACD(事务日志) l (锁+MVCC)

MVCC多版本并发控制中,读操作可以分为两类:
1、快照读(snapshot read)
读的是记录的可见版本,不用加锁。如select

2、当前读(current read)
读取的是记录的最新版本,并且当前读返回的记录。如insert,delete,update,select…lock in share
mode/for update

已提交读(非锁定读):解决脏读问题(读到其他事务未提交的数据),每次执行语句的时候都重新生成一次快照(Read View)。
数据有两种状态(事务commit之前是prepare,提交后是commit)。
每次select查询时,若表中数据是prepare状态,说明有其他事务修改了,此时数据无法产生快照,只能对undo log中的修改之前的数据(commit状态下)产生快照。
当数据被提交后,变为commit状态,或者提交插入了新数据,此时select就会对最新的数据产生快照,于是出现了
不可重复读
幻读

可重复读:,解决不可重复读的问题,同一个事务开始的时候生成一个当前事务全局性的快照(Read View),第一次select查询时。
解决部分虚读的问题原因同上
没解决的那部分幻读:是当事务A对全表生成快照后,事务B插入id=100的数据并提交,此时Aselect是看不到id=100的数据,但是如果A对表进行了update等操作(不是快照读了而是当前读),此时是对最新数据进行操作,而事务是可以看到自己事务修改的数据(匹配数据的DB_TRX_ID),因此下次select就会查看到新数据,产生幻读

快照内容读取原则:
1、版本未提交无法读取生成快照
2、版本已提交,但是在快照创建后提交的,无法读取
3、版本已提交,但是在快照创建前提交的,可以读取
4、当前事务内自己的更新,可以读到

undo log

undo log回滚日志的主要作用:
1、事务发生错误时回滚rollback
2、提供了MVCC的非锁定读〔快照读)

DB_TRX_ID:每个事务都有一个全局ID,存放修改此行数据的事务id
DB_ROLL_PTR:存放地址,存放修改之前的数据的事务id地址
DB_ROW_ID:当没有主键id时,innoDB分配的主键

在这里插入图片描述
undo log实现的过程
在这里插入图片描述

redo log

持久性:事务完成(commit)以后,DBMS保证它对数据库中的数据的修改是永久性的,即使数据库因为故障出
错,服务器掉电等,也应该能够恢复数据!

重做日志,用于记录事务操作的变化,确保事务的持久性。redo log是在事务开始后就开始记录,不管事务是否提交都会记录下来,在异常发生时(如数据持久化过程中掉电),InnoDB会使用redo log恢复到掉电前的时刻,保证数据的完整性。

Buffer Pool Cache是存放在内存结构中的, 对数据的修改先看缓存中有没有数据,没有的话去磁盘中拿进来,当事务对数据进行修改时,不直接对磁盘修改,而是在缓存中修改,缓存中修改完成的叫脏页,脏页由后台线程定时刷入磁盘,Buffer Pool Cache是基于内存的,一旦掉电,数据就丢失了,因此需要redo log
而redo log则是记录事务修改记录的,当事务commit时,是将redo log写入磁盘进行持久化。
问题:为什么commit是将redolog写入磁盘,不直接写数据呢
因为事务的操作会随机的涉及多个数据页,对磁盘随机访问,性能太低,而日志的更新是顺序的追加更新通常只涉及一个数据页。

当数据成功从脏页刷入磁盘中后,redolog也就不需要了,因此redolog是循环刷新的

在这里插入图片描述

在这里插入图片描述

MySQL优化

你对MySQL做过哪些优化?

  • SQL和索引优化
    • 慢查询日志 -》设置慢查询时间 -》 日志中记录的慢查询sql -》explain分析sql执行计划 -》索引的失效,
  • 应用优化
    • 连接池
    • 增加cache缓存层,存储热点数据
      • redis,memcache
  • MySQL server 各种参数的配置, 关闭自适应hash索引, 修改查询缓存的设置(只有表的数据查询频率高,修改频率低才用查询缓存,show variables like ‘%query_cache%’;)

MySQL日志系统

在这里插入图片描述
用户与MySQL Server的网络模块(经典的IO复用+线程池)进行连接,MySQL Server进行语法检查,sql优化等,调用引擎(插拔式)的API,引擎对磁盘的数据进行操作

在MySQL Server还有四种日志

  • 错误日志 MySQLd服务运行过程的错误
  • 查询日志 记录所有sql ,通常在调试时才开启
  • 二进制日志 数据恢复,主从赋值,存储除select外的语句,有定期删除,比如7天,那么7天就进行一次备份,7天前的数据依靠备份
  • 慢查询日志

binlog日志恢复过程

  1. 查看对应的binlog日志,
  2. 找到操作位置的序号
  3. 将找到的起始位置到结束位置的操作,将操作通过管道传入MySQL mysqlbinlog --start-position=775 --stop-position=1410 mysql-bin.000003 | mysql -uroot -p
主从复制

在这里插入图片描述
主从复制的流程:两个日志(binlog二进制日志&relay log日志)和三个线程(master的一个线程和slave的二个线程)
1、主库的更新操作写入binlog二进制日志中。
2、master服务器创建一个binlog转储线程,将二进制日志内容发送到从服务器。
3、slave机器执行START SLAVE命令会在从服务器创建一个IO线程,接收master的binary log复制到其中继日志。首先slave开始一个工作线程(I/O线程),I/O线程在master上打开一个普通的连接,然后开始binlog dump process,binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件,I/O线程将这些事件写入中继日志。
4、sql slave thread(sql从线程)处理该过程的最后一步,sql线程从中继日志中读取事件,并重放其中的事件而更新slave机器的数据,使其与master的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于os缓存中,所以中继日志的开销很小。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值