Mysql后端开发(索引、优化、事务、引擎、锁)

后期有相当多复杂且抽象的概念、一定要理解图中注释才能明白



一、事物基础补全

事物提交

①: 开启事务: START TRANSACTION 或 BEGIN;
①: 提交事务: COMMIT;
①: 回滚事务: ROLLBACK;

事物四大特性

①: 原子性 (Atomicity): 事务是不可分割的最小操作单元,要么全部成功,要么全部失败
①: 一致性(Consistency): 事务完成时,必须使所有的数据都保持一致状态
①: 隔离性 (lsolation): 数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立
①: 环境下运行持久性 (Durability): 事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

并发事务

在这里插入图片描述

事物隔离级别

在这里插入图片描述
越靠下方性能越差!
查看事物隔离级别: SELECT @@TRANSACTION_ISOLATION;
设置事务隔离级别:
SET[SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}}


二、MySQL体系结构(进阶篇)

总体结构

在这里插入图片描述
①: 连接层
最上层是一些客户端和链接服务,主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。
①: 服务层 (优化)
第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如 过程、函数等。
①: 引擎层
存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。
①: 存储层
主要是将数据存储在文件系统之上,并完成与存储引擎的交互

存储引擎

存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被称为表类型。
mysql 5.5版本以后默认存储引擎为: InnoDB

在创建表时,指定存储引擎:
CREATE TABLE 表名(
字段1 字段1类型 [COMMENT 字段1注释],
… 字段n 字段n类型 [COMMENT 字段n注释]
) ENGINE = INNODB [COMMENT 表注释]
查看当前数据库支持的存储引擎:
SHOW ENGINES;

存储引擎特点

INNODB

INNODB是一种兼顾高可靠性和高性能的通用存储引擎
特点:
①: DML操作遵循ACID模型,支持事务
①: 行级锁,提高并发访问性能;
①: 支持外键 FOREIGN KEY 约束,保证数据的完整性和正确性;

xxxibd: xxx代表的是表名,innoDB引擎的每张表都会对应这样一个表空间文件,存储该表的表结构(frm、sdi)、数据和索引。

在这里插入图片描述

MyISAM

MyISAM是MySQL早期的默认存储引擎
特点:
①: 不支持事物,不支持外键
①: 支持表锁,不支持行锁
①: 支持外键 FOREIGN KEY 约束,保证数据的完整性和正确性;
在这里插入图片描述

Memory

Memory引擎的表数据时存储在内存中的,由于受到硬件问题、或断电问题的影响,只能将这些表作为临时表或缓存使用。

特点:
①: 内存存放
①: hash索引(默认)

存储引擎选择

在选择存储引擎时,应该根据应用系统的特点选择合适的存储引。对于复杂的应用系统,还可以根据实际情况洗择多种存储引警进行组合

lnnoDB: 是Mysql的默认存储引擎,支持事务、外键。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致样,数据操作除了插入和查询之外,还包含很多的更新、删除操作,那么InnoDB存储引擎是比较合适的选择。
MyISAM: 如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是非常合适的。
MEMORY: 将所有数据保存在内存中,访问速度快,通常用于临时表及缓存。MEMORY的缺陷就是对表的大小有限制,太大的表无法缓存在内存中,而且无法保障数据的安全性。


三、MySQL索引

由于是核心内容所以单独记录
索引(index)是帮助MySQL高效获取数据的 数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

理解: 假设我们使用 SELECT * FROM user WHERE age = 45; 这样一条查询语句。
没有索引的情况下:
当我们查询过程中找到了表中唯一一条记录的时候,它依然不会停止,会继续向下找。这称之为全表扫描能够想象到这个效率是极低的。
有索引的情况下:
我们会根据索引来更高效的找到我们所需要的记录!

索引的优点: **①:**提高数据检索的效率,降低数据库的IO成本
②: 通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗
索引的缺点: ①: 索引列也是要占用空间的
②: 索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、UPDATE、DELETE时,效率降低。

索引结构

MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含以下几种:
B+Tree索引: 最常见的索引类型,大部分引擎都支持 B+ 树索引
Hash索引: 底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效不支持范围查
R-tree(空间索引): 空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少
Full-text(全文索引): 是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES

在这里插入图片描述

B-Tress(多路平衡查找树)结构

数据结构模拟网站
二叉树缺点: 顺序插入时,会形成一个链表,查询性能大大降低。 大数据量情况下,层级较深,检索速度慢。
红黑树: 大数据量情况下,层级较深。检索速度慢

强烈建议尝试一下B树的数据插入过程,他其实是一个向上分裂的过程
在这里插入图片描述
指针的个数要比key多一个

B+Tress(多路平衡查找树)结构

以一颗最大度数 (max-degree)为4 (4阶)的b+tree为例:
在这里插入图片描述
相对于B-Tree区别:
①: 所有的数据都会出现在叶子节点
②: 叶子节点形成一个单向链表

MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表(双向链表)指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。

这里不够详细,建议各位仔细去看看B和B+的区别和存储逻辑!

Hash索引

①: Hash索引只能用于对等比较(=,in),不支持范围查询 (between,>,<,…)
①: 无法利用索引完成排序操作
①: 查询效率高,通常只需要一次检索就可以了,效率通常要高于B+tree索引

索引分类

在这里插入图片描述
在InnoDB存储引擎中,根据索引的存储形式,又可以分为下列两种:
在这里插入图片描述
聚集索引选取规则:
①: 如果存在主键,主键索引就是聚集索引
①: 如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。
①: 如果表没有主键,或没有合适的唯一索引,则innoDB会自动生成一个rowid作为隐藏的聚集索引。
在这里插入图片描述
先查到二级索引再到聚集索引称之为回表查询

索引语法

创建索引: CREATE [UNIQUE|FULLTEXT] INDEX index _name ON table_name ( index_col_name,…);
create index idx_user_name on tb_user(name);
表中 创建 索引 索引名(idx_表名_字段) on 表名(要创建字段);
查看索引: SHOW INDEX FROM table name;
删除索引: DROP INDEX index_name ON table_name;

索引性能分析

SQL执行频率: MySQL客户端连接成功后,通过 SHOW [SESSION | GLOBAL] STATUS 命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次:

如: SHOW GLOBAL STATUS LIKE ‘Com____’;

慢查询日志:
慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位: 秒,默认10秒)的所有SQL语句的日志
MySOL的慢查询日志默认没有开启,需要在MySOL的配置文件 (/etc/my.cnf)中配置如下信息:在这里插入图片描述
tail -f localhost-slow.log 输入命令它能够实时监控你当前的查询是否超过10s,超过十秒则输出该搜索信息

profile详情:
show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have profiling参数,能够看到当前MySOL是否支持。语句为: select hava_profile
默认profiling是关闭的,可以通过set语句在session/global级别开启profiling
查看是否打开profile: select @@profiling;
打开profiling: set profiling = 1;

执行一系列的业务SQL的操作,然后通过下列指令查看指令的耗时情况:
在这里插入图片描述
我们可以使用 show profiles 来查看所有SQL语句的耗时情况。
然后也可以使用 show profile for query 前面查看到的耗时表中语句序号 然后就能查看这条语句在各个阶段的耗时
开发人员一般也不会去看就是了

explain执行计划:
真正想要判定一个SQL语句的性能还得用 EXPLAIN 或者 DESC 命令获取MySQL 如何执行 SELECT 语句的信息,包括在SELECT语句执行过程中如连接和链接的顺序
语法:
在这里插入图片描述

explain执行计划各个字段含义:
id: select查询的序列号,表示查询中执行select子句或者是操作表的顺序(id相同,执行顺序从上到下;id不同,值越大,越先执行)。
select_type: 表示 SELECT 的类型,常见的取值有 SIMPLE (简单表,即不使用表连接或者子查询)、PRIMARY(主查询,即外层的查询)
UNION(UNION 中的第二个或者后面的查询语句)、SUBQUERY (SELECT/WHERE之后包含了子查询)等
type: 表示连接类型,性能由好到差的连接类型为NULL、system、const(唯一性索引)、eq_ref、ref(非唯一性索引)、range、index、all
tyep越靠前性能越高
possible_key: 显示可能应用在这张表上的索引,一个或者多个
Key: 实际使用的索引,如果为NULL,则没有使用索引
Key_len: 表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好
rows: MySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值,可能并不总是准确的
filtered: 表示返回结果的行数占需读取行数的百分比,filtered 的值越大越好

索引使用

索引的验证: 可以自己去下载一张千万数据的表,先回表查询一下看看用时,然后你在创建一个索引,再查询一下看看用时,只能说B+树无敌

最左前缀法则:
如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将部分失效(后面的字段索引失效)

说人话就是,当你在搜索联合索引的字段时,你的SELECT语句如果跳过第一个字段,搜索后面的字段。这时候就不会用到联合索引而是直接全表扫描。
你从哪里开始跳过,那么从跳过的字段之后都不会采用索引,都用全表扫描。
如果你查询了联合索引中的每一个字段,那就可以不考虑顺序,他都一定会全部查询

范围查询:
联合索引中,出现范围查询(>,<) 范围查询右侧的列索引失效
可以使用 >= 或 <= 来进行查询,这样就可以规避索引失效的问题

索引列运算:
不要再索引列上进行运算操作,索引将失效

字符串不加引号:
字符串类型字段使用时,不加引号,索引将失效

模糊查询:
如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。

or连接的条件:
用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。

数据分布影响:
如果MySQL评估使用索引比全表扫描还慢,就不用索引扫描了。

SQL提示:
use index只是建议sql用这个索引,至于用不用取决于它自己
在这里插入图片描述

覆盖索引:
尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中色经全部能够找到),减少select *
意思就是少用 * 换成你所要检索的字段就是了
在这里插入图片描述

前缀索引:
当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘10,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
语法:
在这里插入图片描述
前缀长度:
可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
计算语法:
在这里插入图片描述

这里指代的是字段类型当中数据的前几个字符、而不是字段名的前几个字符
图解:
在这里插入图片描述

单列索引与联合索引:
单列索引: 即一个索引只包含单个列。
联合索引: 即一个索引包含了多个列。
在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引,而非单列索引。
多条件联合查询时,MySQL优化器会评估哪个字段的索引效率更高,会选择该索引完成本次查询

联合索引的B+
在这里插入图片描述

索引设计原则:
在这里插入图片描述


四、SQL优化

插入数据INSERT

当我们一次性插入多条数据的时候,采用**批量插入**:
Insert into tb test values(1,'Tom'),(2,'Cat'),(3, Jerry');

之前我们学习过事务,当你每次插入数据它会自动提交,每一次提交也需要耗费资源
因此我们使用**手动提交事务**:
start transaction;
insert into tb test values(1,‘Tom’),(2,‘Cat’),(3,Jerry’);
insert into tb test values(4,‘Tom’),(5,‘Cat’),(6,Jerry’);
insert into tb test values(7,‘Tom’),(8,‘Cat’),(9,Jerry’);
commit;

主键顺序插入
几百万条数据的情况下使用 load data这条语句、效率很高!
在这里插入图片描述

主键优化

数据组织方式
在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table lOT。

页分裂(乱序插入):
页可以为空,也可以填充一半,也可以填充100%。每个页包含了2-N行数据(如果一行数据多大,会行溢出),根据主键排列。
在这里插入图片描述
当第一页快满了,要插入一个很大的数据,但是又插不进去。此时会开一个新的页,取出第一页当中的一半放到新页当中,然后把很大的数据接在后面

页合并:
当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。
当页中删除的记录达到 MERGE THRESHOLD(默认为页的50%),nnoDB会开始寻找最靠近的页(前或后)看看是否可以将两个页合并以优化空间使用。
在这里插入图片描述

主键设计原则:
满足业务需求的情况下,尽量降低主键的长度。
插入数据时,尽量选择顺序插入,选择使用AUTO INCREMENT自增主键
尽量不要使用UUID做主键或者是其他自然主键,如身份证号(因为这些东西都不是顺序的)

order by优化

explain语句 最后一天 Extra能够看到当前使用方式。不是索引就针对你想要的字段建立一个索引就行
①: Using flesot: 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sotbuffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。
①: Using index: 通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要额外排序,操作效率高。
联合索引查询多个字段同样要遵守最左前缀法则、才能够保证你搜索的时候都是Using index

有一种情况,当你创建一个索引,你希望一个按升序排列当遇到相同的时候,则比较另一个字段用降序排列。此时你可以在创建索引的时候在索引名后方 加上 asc 或者 desc! 这样就可以Using index 不写默认为升序ASC
在这里插入图片描述

group by优化

Using temporary: 这个也是效率低
其他的基本跟order by一样、也是自己建一个联合索引,记得遵循最(左前缀法则)

limit优化

一个常见又非常头疼的问题就是 limit 2000000,10,此时需要MySOL排序前2000010 记录,仅仅返回2000000 -2000010的记录,其他记录丢弃,查询排序的代价非常大。
优化思路:一般分页查询时,通过创建 覆盖索引 能够比较好地提高性能,可以通过覆盖索引加子查询形式进行优化。
在这里插入图片描述

count优化

MVISAM引擎把一个表的总行数存在了磁盘上,因此执行count)的时候会直接返回这个数,效率很高》InnoDB引擎就麻烦了,它执行 count(*)的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。优化思路: 自己计数

count的几种用法
count)是一个聚合函数,对于返回的结果集,一行行地判断,如果count函数的参数不是 NULL,累计值就加1,否则不加,最后返回累计值。
用法: count (*)、count (主键) 、count (字段) 、count (1) 字段的话要看是不是null

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

update优化

在update数据的时候,条件有索引就是行锁、没有索引就是表锁
执行update的时候一定索引字段进行更新,否则就会行锁升级为表锁。这样会降低并发性能


四、视图/存储过程/触发器

视图

视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。
通俗的讲,视图只保存了查询的SQL逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条SOL查询语句上。
语法:
我们可以在创建视图的时候在语句最后加上 with cascaded/local check option; 它能够检查你的插入语句是否符合视图创建时的条件
在这里插入图片描述
replace: 表示替换或者创建、视图名字自己起,SELECT FROM 表名 WHERE 条件;
在这里插入图片描述
在这里插入图片描述

视图检查

当使用WITH CHECK OPTION子句建视图时,MySQL会通过视图检查正在更改的每个行,例如 插入,更新,删除,以使其符合视图的定义。MySOL允许基于另一个视图创建视图,它还会检查依赖视图中的规则以保持一致性。为了确定检查的范围,mysql提供了两个选项:CASCADED 和 LOCAL,默认值为CASCADED。
视图是可以在另一张视图的基础上再建立的
在这里插入图片描述
如果你此时再建立一个视图 V3 它基于 V2建立,那么此时它本身的条件并不会局限你插入、删除数据。但是它会回头去检查你基于的视图要求,比如上图的V2和V1的条件,也是要满足的,才能够修改数据!

  1. 所有条件都会检查
  2. 后面有check option的检查不通过会报错
  3. cascade和local的区别在于前者会将check option向上传递

在这里插入图片描述
视图的作用:
简单:
视图不仅可以简化用户对数据的理解,也可以简化他们的操作。那些被经常使用的查询可以被定义为视图,从而使得用户不必为以后的操作每次指定全部的条件。
安全:
数据库可以授权,但不能授权到数据库特定行和特定的列上。通过视图用户只能查询和修改他们所能见到的数据。比如我表当中有一些数据不想别人看到,我可以创建一个视图里面并不加入这些数据。以此来隐藏一些敏感信息!
数据独立:
视图可帮助用户屏蔽真实表结构变化带来的影响。比如我表中本来有个字段名是name,由于业务缘故我需要修改表中字段名、这时候我可以直接在创建视图语句的字段后面加上 别名 AS来修改视图当中的字段名。以此来免除业务对视图的影响

存储过程

当我们需要修改一个内容的时候、需要先查询看到内容,在update更新数据。每一次操作都要反复如此。因此我们出现了存储过程,把SQL语言代码封装与重演。你可以理解为定义好的Java方法,你只需要调整参数就能够轻松多次使用~

存储过程是事先经过编译并存储在数据库中的一段 SOL 语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。
存储过程思想上很简单,就是数据库 SOL 语言层面的代码封装与重用。

特点: 封装、复用
可以接收参数、也可以返回数据、减少网络交互提升效率

语法:
在这里插入图片描述
调用: CALL 名称 ([参数])
查看: 一个是查看数据库、一个是查看存储过程的定义内容等等(存储过程也可以在routines里面查看)
在这里插入图片描述
删除:
在这里插入图片描述
在这里插入图片描述
我们把创建存储过程的语句放在finalshell里面运行时,检测到分号就会自动报错,因此我们可以使用delimiter来定义一个结束符。比如 delimiter $$ 这样,当它运行到分号也不会结束,它会一直等到两个 $ 出现

变量:
系统变量 是MySQL服务器提供,不是用户定义的,属于服务器层面。分为全局变量 (GLOBAL)、
会话变量 (SESSION)
用户定义变量 是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用“@变量名”使用就可以。其作用域为当前连接
查看系统变量:
在这里插入图片描述
设置系统变量:
在这里插入图片描述

用户自定义变量:
建议赋值使用 := 因为在SQL当中没有 == ,比较和赋值都是用=号,便于区分我们赋值尽量使用:=
变量不需要声明、直接赋值就行,如果你没有赋值的话拿出来就是null
在这里插入图片描述
局部变量
局部变量是根据需要定义的在局部生效的变量,访问之前,需要DECLARE声明。可用作存储过程内的局部变量和输入参数,局部变量的范围是在其内声明的BEGIN …END块。
在这里插入图片描述

if语法

在这里插入图片描述
关于存储过程当中的参数: 配合用户自定义变量等、来完成各种需求和类型的输入输出!
在这里插入图片描述

case

这个直接就是switch 没啥好说滴、case_value的值决定它执行下面的哪一条语句
在这里插入图片描述
在这里插入图片描述

while:

while 循环是有条件的循环控制语句。满足条件后,再执行循环体中的SQL语句。具体语法为:
在这里插入图片描述

repeat:

理解为do while
在这里插入图片描述

loop:

break和 continue在这里插入图片描述
前面括号中的内容是你给loop起的名字 ; leave 和 iterate 后面是你的loop名字
当你在loop当中写 if 来判断退出条件的时候切记 end if;

游标

在之前的自定义变量中、我们赋值语句有提到,从某张表搜索字段然后存取到我们自定义的变量中。
但它其实有个前提,那就是你所搜索的字段必须由同样数据类型的变量来存放!
如果你定义一个int变量 那又要如何存放一整条记录呢?
游标(CURSOR)是用来存储查询结果集的数据类型,在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPEN、FETCH 和 CLOSE,其语法分别如下。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

条件处理程序

理解为抛出异常
条件处理程序 (Handler)可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。具体语法为:
在这里插入图片描述

存储函数

存储函数是有返回值的存储过程,存储函数的参数只能是IN类型的。具体语法如下

在这里插入图片描述

存取函数和过程的区别

在这里插入图片描述

触发器

触发器是与表有关的数据库对象,指在 insert/update/delete 之前或之后,触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性,日志记录,数据校验等操作使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还只支持行级触发,不支持语句级触发
在这里插入图片描述
触发器相关语法:
在这里插入图片描述
创建插入触发器举例:
建表时切记: create table user_logs user_logs 是一个触发器的日志表,触发器当中重写的那个“toString”就会写进日志表。
for each row:行级触发器、也就是每一行数据发生变动都会记录!
注意: 增、删、改 都能够记录在同一张触发器日志之下!
在这里插入图片描述
之前我们除了 NEW还提到了OLD OLD表示的是更新之前的数据、NEW表示的是更新之后的数据。我们都能能够通过触发器日志来记录下表中所有数据变化、这样呢,即使你删表跑路也能找出相对应时间来证明起诉你


五、锁

共享锁是读锁、排他锁是写锁
共享锁是读锁、排他锁是写锁
共享锁是读锁、排他锁是写锁
我认为这样能够方便理解重要的事情说三遍

锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、1/0)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。
关于锁的知识我们在Java多线程中也能学习到、释放锁、死锁、互斥锁、轻量级锁、重量级锁、自旋锁、偏向锁、读写锁等

锁的分类

按照锁的粒度来分、共有三种:
全局锁: 锁定数据库中的所有表。
表级锁: 每次操作锁住整张表。
行级锁: 每次操作锁住对应的行数据

全局锁

全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。
其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
如果阻塞了的话,要等到锁释放了才可以继续执行
在这里插入图片描述
那么如果我先锁住三张表、此时黄色的业务程序并不能修改数据、只能够读写用来备份数据。备份完之后再释放锁、如此一来我们就能拿到一份数据统一的表格

语法三步骤:
上锁: flush tables with read lock;
备份: mysqldump -u root -p 表名 > 表名路径.sql
释放锁: unlock tables;

特点:
数据库中加全局锁,是一个比较重的操作,存在以下问题:
全局锁不仅仅会锁住一个数据库,如果会锁住所有数据库
如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆
如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志 (binlog),会导致主从延迟
主库的日志已经更新了、从库这边日志还被锁着、也会影响!

为了解决这个问题,在innoDB引擎中,我们可以在备份时加上参数 --single-transaction 参数来完成不加锁的一致性数据备份。
在这里插入图片描述
用这个语句备份就可以不加锁的时候被分到一致性的数据

表级锁

表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中。
表级锁共有三种:

表锁(读写锁)

①: 表共享读锁(read lock)
②: 表独占写锁(write lock)
语法:
加锁: lock tables 表名 … read/write
释放锁: unlock tables / 客户端断开连接
在这里插入图片描述
写锁只当前上锁客户端能读能写,其他客户端一律不能读写

元数据锁(meta data lock, MDL)

元数据可以简单的理解为标结构
MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作,这是为了避免DML与DDL冲突,保证读写的正确性
在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共);当对表结构进行变更操作的时候,加MDL写锁(排他)
在这里插入图片描述
在这里插入图片描述

意向锁

为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。
没有意向锁的情况下:
在这里插入图片描述
有意向锁的情况下:
在这里插入图片描述

意向锁的两种:
在这里插入图片描述
意向共享锁和读锁(read)是兼容的 ; 与表锁排他锁(write)互斥
意向排他锁与读锁(read)及排它锁(write)都互斥,意向锁之间不会互斥

在这里插入图片描述

行级锁

行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。
在这里插入图片描述
理解图中每一句话! 有了间隙锁可以保证使用期间不会被其他事务插入而导致幻读

行锁

在这里插入图片描述
这个地方有点难理解 看我的梳理
共享锁允许多个事务同时读取同一行,但不允许任何事务修改该行。这意味着共享锁可以防止脏读(一个事务读取到另一个事务还没提交的数据),但不能防止并发修改。排他锁只允许一个事务同时读取和修改同一行。这意味着排他锁可以防止并发修改,但不能防止脏读。
在MySQL中,共享锁和排他锁之间存在一定的互斥关系。如果一个事务持有共享锁,则另一个事务不能持有排他锁。同样,如果一个事务持有排他锁,则另一个事务不能持有共享锁。这是为了确保数据的一致性和完整性。

在这里插入图片描述

在这里插入图片描述
当然如果你创建了索引、InnoDB就不会升级为表锁了,依然是行锁!

间隙锁

在这里插入图片描述
注意:间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。
在这里插入图片描述


六、InnoDB引擎

逻辑存储结构

在这里插入图片描述

架构-内存架构

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

事务原理

redo log (持久性)

物理日志只是记录这个数据里面的内容是什么样的
重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。该日志文件中两部分组成:重做日志缓冲(redolog bufer)以及重做日志文件(redo og fle)前者是在内存中,后者在磁盘中。当事提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用
在这里插入图片描述
当我们Buffer Pool的数据成功刷新到磁盘之后、Redolog的日志文件也就不需要了。所以通常会定期清理这两个日志文件

undo log (原子性)

逻辑日志只是记录每一步执行的是什么样的操作
回滚日志,用于记录数据被修改前的信息,作用包含两个: 提供回滚 和 MVCC(多版本并发控制)。
undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo og中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。当执行rollback时,就可以从undolog中的逻辑记录读取到相应的内容并进行回滚。
Undolog销毁: undolog在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC
Undo log存储: undo log采用段的方式进行管理和记录,存放在前面介绍的 rolback seqment 回滚段中,内部包含1024个undo logsegment.

MVCC

当前读
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如: select … lockin share mode(共享锁),select … for update、 update、insert、delete(排他锁)都是一种当前读.
快照读
在这里插入图片描述

MVCC概念:
全称 Multi-Version Concurrency ontrol,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySOL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readvView。
打错了是ibd文件
在这里插入图片描述

undo log版本链

在这里插入图片描述

readview

ReadView(读视图)是 快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。ReadView中包含了四个核心字段:
我们的快照读在读取数据的时候具体要读undo log 中的哪一个版本就是根据readview来决定的
在这里插入图片描述
不同的隔离级别,生成Readview的时机不同:
READ COMMITTED: 在事务中每一次执行快照读时生成ReadView。
REPEATABLE READ: 仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。
在这里插入图片描述
在这里插入图片描述


七、MySQL管理

系统数据库

Mysql数据库安装完成以后,自带了一下四个数据库、具体作用如下:
这些都是你创建一个数据库之后自带的内容、也是一些表来记录各种信息的
在这里插入图片描述

常用工具

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值