MySQL进阶(包含事务、引擎、索引、锁等知识点)

MySQL事务

MySQL默认的事务提交是自动的,要想手动开启事务可以使用start transaction 或者 begin 指令。 提交事务使用 commit 指令。 回滚事务使用 rollback

事务的四大特性(ACID):

  1. 原子性(atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败

  2. 一致性(consistency):事务完成时,必须所有的数据保持一致性

  3. 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响独立环境下运行

  4. 持久性(Durability):事务一旦提交对数据库中数据改变是永久的

并发事务问题

  1. 脏读:一个事务读到另一个事务还没提交的数据

  2. 不可重复读:一个事务先后读取同一条记录,单两次读取的数据不同。

  3. 幻读:一个事务按照条件查询数据时没有对应的数据行,但是在插入数据时,又发现这行数据已经存在了,好像出现了“幻影”

事务隔离级别

请添加图片描述

存储引擎

MySQL体系架构

  1. 连接层
    最上层的一些客户端和链接服务,包括本地sock通信和大多数基于C/S工具实现的类似于TCP/IP的通信。
    主要的工作是完成连接处理授权认证、以及相关安全方案
    在该层引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。

  2. 服务层
    完成大多数的核心服务功能,例如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如过程,函数等
    服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定表的查询的顺序,是否利用索引等、最后生成对应的执行操作。如果是select语句,服务器还会查询内部的缓存,如果缓存空间足够大,这样解决大量读操作的环境中能够很好的提升系统的性能。

  3. 引擎层
    存储引擎层,负责MySQL中数据的存储和提取,服务器通过API和存储引擎进行通信。不同存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。数据库中的索引是在存储引擎层实现的。

  4. 存储层
    数据存储层,主要将数据(如:redolog、undolog、数据、索引、二进制、错误日志、查询日志、慢查询日志等)存储在文件系统之上,并完成与存储引擎的交互。

插件式的存储引擎架构,将查询处理和其他的系统业务以及数据的存储提取分离。

存储引擎

存储引擎式是存储数据建立索引更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,因此存储引擎也被称为表类型。

在创建表的时候可以指定存储引擎。没有指定的话会使用默认的存储引擎。

例如:

create table table_name(...........
)engine = innodb;

可以使用指令查询MySQL所有的存储引擎

show engines;

存储引擎的特点

主要简述InnODB、MyISAM,Memory的特点。

InnoDB(default)

特点:

  1. DML操作遵循ACID模型,支持事务

  2. 行级锁、提高并发访问性能

  3. 支持外键、保证数据的完整性、正确性

逻辑存储结构:
在这里插入图片描述

  • 表空间:逻辑存储的最高层,ibd文件其实就是表空间文件,在表空间中还可以包含多个Segment段。

  • 段:常见的段有数据段、索引段、回滚段等。 对于段的管理、都是由引擎自身完成,不需要人为对其控制,一个段包含多个区。

  • 区:区是表空间的单元结构,每个区的大小为1M。默认情况下,InnoDB存储页的大小为16K,即一个区中有64个连续的页。

  • 页:组成区的最小单元,页也是InnoDB存储引擎管理的最小单元,每个页大小为16K。为了保证页的连续性,InnoDB存储引擎每次从磁盘申请4-5个区。

  • 行:InnoDB存储引擎面向行,也就是说数据是按照行进行存放的、每一行除了定义表时所指定的字段外,还包含两个隐藏字段。

MyISAM

特点

  1. 不支持事务和外键

  2. 支持表锁、不支持行锁

  3. 访问速度快

Memory

特点

  1. 内存存放

  2. hash索引

区别和特点

在这里插入图片描述

存储引擎的选择
  • InnoDB:默认存储引擎。支持事务、外键。对事务完整性有较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新、删除操作那么InnoDB比较合适。

  • MyISAM:如果以读和插入数据为主,只有很少的更新和删除操作,并且对事务的完整性,并发性要求不是很高,那么可以选用。

  • Memory:所有数据存储在内存中,访问速度快,通常用于临时表以及缓存。缺陷就是对表的大小有限制,太大的表无法缓存在内存中,而且无法保障数据的安全性。

索引

概述

MySQL的索引再存储引擎层实现,不同的引擎有不同的索引结构;

在这里插入图片描述

MySQL中不同的引擎对应的索引结构;

在这里插入图片描述

索引的分类

在MySQL中,索引的具体类型主要分为:主键索引、唯一索引、常规索引、全文索引。

在这里插入图片描述

InnoDB中的索引

在InnoDB中,根据索引的存储形式,分为:聚集索引(Clustered Index)、二级索引(Secondary Index)

在这里插入图片描述

聚集索引选取的规则:

  • 如果存在主键,主键索引就是聚集索引。

  • 如果不存在主键,那么将使用第一个(UNIQUE)索引作为聚集索引。

  • 如果表没有主键,或没有合适的唯一索引,那么InnoDB会自动生成一个rowid作为隐藏的聚集索引。

聚集索引和二级索引的具体结构如下:

在这里插入图片描述

聚集索引的叶子节点下挂的是这一行的数据。

二级索引的叶子节点下挂的是该字段值对应的主键值。

如果查询语句走的是二级索引那么会从索引中找到对应的主键值,然后回表查询

索引语法

创建索引

CREATE [UNIQUE|FULLTEXT] INDEX index_name ON table_name (index_col_name,.....);

查看索引

SHOW INDEX FROM table_name;

删除索引

DROP INDEX index_name ON table_name;

SQL性能分析

SQL执行频率

使用show [session|global] status 命令可以提供服务器状态信息。可以使用这条语句去查看数据库INSERT,UPDATE,DELETE,SELECT的访问频次。

--session 是查看当前会话;
--global 是查询全局数据;
SHOW GLOBAL STATUS LIKE 'Com_______';

在这里插入图片描述
Com_delete:删除次数

Com_insert:插入次数

Com_select:查询次数

Com_update:更新次数

通过这条语句我们就能查看数据库各个语句的执行频率,我们就能知道当前的数据库是增删为主还是查询为主。

慢查询日志

慢查询日志记录所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。
在这里插入图片描述
默认是关闭的。

如果要开启慢查询日志,需要在MySQL·的配置文件(/etc/my.cnf)中进行配置;

#开启MySQL慢查询日志开关
slow_query_log = 1
#设置慢查询日志的时间2秒,SQL语句执行超过两秒的,就会视为慢查询,记录慢查询日志
long_query_time = 2

也可以通过指令去开启和设置;

SET GLOBAL slow_query_log = 1;SET long_query_time = 2;

使用指令查看mysql的日志,日志中记录了慢查询查询语句;

tail -f localhost-slow.log

profile详情

show profiles 能够在做SQL优化时帮助我们了解时间否耗费到哪里去了。通过have_profiling参数,能够看到当前MySQL是否支持profile操作;

--查看是否支持profile
SELECT @@have_profiling;
--查看是否开启profileSELECT @@profiling;

在这里插入图片描述

--开启profiling 可以使用session|global设置开启的profiling级别
SET profiling = 1;
--查看每一条SQL的耗时情况
SHOW profiles;--查看指定query_id的SQL语句各个阶段的耗时情况
SHOW profile for query query_id;--查看指定query_id的SQL语句CPU的使用情况
SHOW profile cpu for query query_id;

explain

expain或者desc命令获取MySQL如何执行select语句的信息,包括select语句执行过程中表如何连接和连接的顺序。

--直接在select语句之前加上关键字explain/descEXPLAIN SELECT * FROM tb_user WHERE id = 1;

explain执行计划中各个字段的含义;

在这里插入图片描述

索引使用

最左前缀法则

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

最左前缀法则中指的是最左边的列,是指在查询时,联合索引的最左边的字段(即第一个字段)必须存在,与编写SQL时,条件编写的先后顺序无关。

范围查询

联合索引中,出现范围查询(<,>),范围查询右侧的列索引失效。

--创建索引
create index tb_user_pro_age_status on tb_user (profession,age,status);--使用explain语句去分别查看查询语句的索引的长度
explain select * from tb_user where professon = 'ruanjiangongcheng' and age > 30 and status = '0';
#age 后面的字段status没有走索引explain select * from tb_user where profession = 'ruanjiangongcheng' and age >= 31 and status = '0';
#所有的字段都走索引

所以,在业务允许的情况下,尽可能的使用类似于>=或<=这类的范围查询,而避免使用>或<。

索引失效情况

  • 索引列运算

    create index tb_user_phone on tb_user(phone);--给phone字段加函数运算
    explain select * from tb_user where substring(phone,10,2)='15';
    #索引失效
    
  • 字符串不加引号

    explain select * from tb_user where phone = '19958763262';--索引失效的情况
    explain select * from tb_user where phone = 19958763262;
    
  • 模糊查询

    --索引不失效
    explain select * from tb_user where profession like 'ruanjian%';
    --索引失效
    explain select * from tb_user where profession like '%ruanjian';
    --索引失效
    explain select * from tb_user where profession like '%ruanjian%';
    
  • or连接条件

    --age字段没有索引即使 id 和 phone 字段有索引 索引也都失效
    explain select * from tb_user where id = 10 or age = 23;
    explain select * from tb_user where phone = '19958763262' or age = 23;
    
      当使用or连接的条件,左右两侧字段都有索引时,索引才会生效。
    

SQL提示

SQL提示,是优化数据库的一个重要手段,简单来说,在SQL语句中加入一些人为的提示来达到优化操作的目的。

  1. use index ; 建议MySQL使用哪一个索引完成此次查询(仅是建议,MySQL内部还会再次进行评估)。

    explain select * from tb_user use index (tb_user_pro) where profession = 'ruanjiangongcheng';
    
  2. ignore index ; 忽略指定的索引

    explain select * from tb_user ignore index(tb_user_pro) where profession = 'ruanjiangongcheng';
    
  3. force index ; 强制使用索引

    explain select * from tb_user force index(tb_user_pro)where profession = 'ruanjiangongcheng';
    

前缀索引

当字段类型为字符串(varchar,text,longtext等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费磁盘大量IO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。

create index idx_xxxxxx on table_name(column(n));
  1. 前缀的长度 ; 根据索引的选择性来确定,而选择性时指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的选择性,性能也是最好的。

    select count(distinct email) / count(*) from tb_user;
    select count(distinct substring(email,1,5)) / count(*) from tb_user;
    
  2. 前缀索引的查询流程
    在这里插入图片描述

索引设计原则

  1. 针对数据量较大,且查询比较频繁的表建立索引。

  2. 针对常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。

  3. 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率就越高。

  4. 如果是字符串类型的字段,字段的长度较长,可以针对字段的特点,建立前缀索引。

  5. 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。

  6. 要控制索引的数量,索引也不是多多益善,索引越多,维护索引结构的代价越大,会影响增删改的效率。

  7. 如果索引列不能存储NULL值,在建立表的时候用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好的确定哪个索引最有效的用于查询。

SQL优化

插入数据

insert

如果一次性往数据库插入多条记录,可以从三方面进行优化。

  1. 批量插入数据

    insert into tb_test values(1,'tom'),(2,'cat'),(3,'jerry');
    
  2. 手动控制事务

    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;
    
  3. 主键顺序插入,性能高于乱序插入

大批量插入数据

一次性需要插入大批量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令进行插入。

--客户端连接服务器时,加上参数 --local-infile
mysql --local-infile -u root -p--设置全局参数local_infile为1,开启本地加载文件导入数据的开关
set global local_infile  = 1;--执行load指令将准备好的数据,加载到表结构中
load data local infile '/root/sql1.log' into table tb_user fields terminated by '.' lines terminated by '\n';
主键优化
  1. 数据组织方式:在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table IOT)。
    在这里插入图片描述

    行数据存储在B+树的叶子结点上。

    在这里插入图片描述

    在InnoDB中,数据行时记录在逻辑结构page页中的,每个页的大小时固定的,默认16K。这意味着,一个页中所存储的行也是有限的,如果插入的数据行row在该页存储不下,就会存储到下一个页中,页与页之间通过指针连接。

  2. 页分裂
    页可以为空,也可以填充一半,也可以填充100%。每个页包含了2-N行数据(如果一行数据过大,会行溢出),根据主键排列。
    A.组件顺序插入效果
    1)从磁盘中申请页,主键顺序插入

    2)第一个页没有满,继续往第一个页插入
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/c040f0daddaa438cbb7de68c02c322f8.png

    3)当第一个也写满之后,再写入第二个页,页与页之间会通过指针连接
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UtodKQEL-1682170047614)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/a04d24fe-7211-453f-a203-43c9a0c9a5c2.png)]
    4)当第二个页写满了,再往第三页写入
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jhbJwaY1-1682170047615)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/4ed5df38-479c-4645-a373-763d69fdb931.png)]
    B.主键乱序插入效果
    1)加入1#,2#页都已经写满了,存放了如图所示的数据
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6U0fUR6L-1682170047615)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/f93761d8-5909-4b3f-b396-774c67c29e8f.png)]
    2)此时再插入id为50的记录,我们来看看会发生什么现象
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zhAofAMU-1682170047615)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/e9188bd4-3fd5-42b1-af26-e272b3fe4686.png)]
    50号要按照顺序存储再47之后。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DxfwWSTa-1682170047616)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/978ee9b6-34e5-44cf-a7cd-b39ad84e88e0.png)]
    但是47所在的1#页,已经写满了,存储不了50对应的数据,此时会开辟一个新的页3#。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kZrcau2g-1682170047616)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/756f383f-c4dc-40d1-b6cf-20ac9b23b486.png)]

但是并不会直接将50存入3#,而是将1#页后一半的数据,移动到3#页,然后在3#页插入50.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fzS9MTz5-1682170047616)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/7a36a5ed-78cd-49a2-b2b8-f219d2bd4966.png)]

移动数据,并插入id为50的数据之后,那么此时,这三个页之间的数据顺序是有问题的。1#的下一个页,应该时3#,3#的下一个页时2#,所以此时要重新设置链表指针。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jmUTs3G7-1682170047616)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/0a14aea9-24fd-43f8-bccc-4213e2b4d70a.png)]

  1. 页合并

假设目前表中已有数据的索引结构如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fRzvPc7Q-1682170047617)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/50a94390-6878-4592-a1d7-c2d34b2941e0.png)]

当我们对已有数据进行删除时,具体的效果如下:

当删除一行记录时,实际上记录并没有物理删除,知识被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QyKHR1UV-1682170047617)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/e3c1b0a6-efd7-4b9e-99c7-44f36576b3c9.png)]

当我们继续删除2#的数据记录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NQlCHBz1-1682170047617)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/e059ee5f-2466-463f-807b-15728718b9fb.png)]

当页中删除的记录达到MERGE_THRESHOLD(默认为50%),InnoDB会开始寻找最靠近的页(前或者后)看看是否可以将两个页合并以优化空间使用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GeBS0GX6-1682170047617)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/3bdddce4-210b-49e8-be62-e3a61d5141aa.png)]

删除数据,并将页合并之后,再次插入新的数据21,则直接插入3#页

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DhCMXhF6-1682170047618)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/85c1183e-255a-41fd-85e2-c923665ce51f.png)]

  1. 主键设计原则
    在满足业务需求的情况下,尽量降低主键的长度。
    插入数据的时候,尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键。
    尽量不要使用UUID做主键或者是其他的自然组件,如身份证号。
    业务操作时,避免对主键的修改。

order by 优化

MySQL的排序有两种方式:

Using filesort : 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫FileSort。

Using index:通过有序索引顺序扫描直接返回有序数据,这种情况即为using index , 不需要额外排序,操作效率高。

using index 的效率要高于 using filesort

order by优化原则:

  1. 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。

  2. 尽量使用覆盖索引。

  3. 多字段排序,一个升序一个降序,此时需要注意联合索引创建时的规则(ASC/DESC)。

  4. 如果不可避免的出现filesort,大数据排序时,可以适当增大排序缓冲区大小sort_buffer_size。

group by优化

  1. 在分组操作时,可以通过索引来提高效率

  2. 在分组操作时,索引的使用也是满足最左前缀法则

limit优化

在进行分页查询时,如果执行limit 2000000,10 , 此时需要MySQL排序前2000010条记录,仅仅返回2000000-2000010的记录,其他记录丢弃,排序的代价非常大。

优化思路:一般分页查询时,通过创建覆盖索引能够比较好提高性能,可以通过覆盖索引加子查询形式进行优化。

count优化

在测试中,我们发现,数据量很大,在执行count操作时,非常耗时。

  • MyISAM将总数记录到磁盘上,因此执行了count(*)会返回这个数,效率较高,但是如果带条件的count,MyISAM也慢

  • InnoDB在执行count(*)的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。

如果要大幅度提升InnoDB地count效率,主要地优化思路:自己计数(可以借助于redis这样地数据库进行,但是如果是带条件地count又比较麻烦)。

count用法

count()是一个聚合函数,对于返回地结果集,一行行地判断,如果count函数的参数不是NULL,累计值就加1,否则不加,最后返回累计值。

用法:count(*),count(主键),count(字段),count(数字)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tZQHkF1f-1682170047618)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/69a3c375-b35b-41f6-b828-e689570785ae.png)]

count(字段)

update优化

update course set name = 'javaEE' where id = 1;
-- 当我们执行这条SQL语句时,会锁定id为1的这一行的数据,然后事务提交之后,行锁释放update course set name = 'springboot' where name = 'PHP';
--当我们开启多个事务,在执行上述的SQL时,行锁升级为表锁,update语句性能降低。

InnoDB的行锁时针对索引加的,不是针对记索引不能失效,否则从行锁升级为表锁。

全局锁

全局锁对整个数据库实例加锁,加锁之后整个实例就处于只读状态,后续的DML语句,DDL语句,已经更新操作的事务都将阻塞。

典型的应用场景就是数据库的备份。

  1. 加全局锁

    flush tables with read lock;
    
  2. 数据备份

    mysqldump -uroot -p1234 table_name > tbale_name.sql;
    
  3. 释放锁

    unlock tables;
    

特点

数据库中加全局锁存储一些问题:

  • 从主库上备份,那么备份期间都不能执行更新,业务基本上就得停摆。

  • 如果从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。

在InnoDB引擎中,我们可以备份时加上参数–single-transaction参数来完成不加锁的一致性数据备份。

mysqldump --single-transaction -uroot -p123456 databese_name > databse_name.sql;

表级锁

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

表锁

  • 表共享锁(read lock)

  • 表独占锁(write lock)

读锁不会阻塞其他客户端的读,但会阻塞写。写锁即会阻塞其他客户端读又会阻塞其他客户端的写。

lock tables tbale_name read/write;
unlock tabels;

元数据锁(metadata lock)

MDL加锁由过程由系统自动控制,无需显示使用,在访问一张表的时候会自动加上。主要的作用就是维护表元数据一致性,在表上有事务的时候不可以对元数据进行写入操作。为了避免DML和DDL冲突,保证读写的正确性。

常见的SQL操作时,所添加的元数据锁:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vl7YUrt4-1682170047618)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/8008ef49-366f-4516-a2e4-7440f5de07b7.png)]

意向锁

为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。

  • 意向共享锁(IS):由语句select … lock in share mode 添加。 与表锁共享锁(read)兼容, 与表锁排他锁(wirte)互斥。

  • 意向排他锁(IX):由 insert 、 update 、delete 、select … for update添加。与表锁共享锁(read) 排他锁(write)都互斥,意向锁之间不会互斥。

一旦事务提交,意向共享锁,意向排他锁,都会自动释放。

--查看数据的加锁情况
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;

行级锁

行级锁,每次操作锁住对应的行数据。锁粒度最小,发生锁冲突的概率最低,并发度最高。应用再InnoDB引擎中。

行锁(Record Lock)

锁定单个行记录的锁,防止其他事务对此行进行update 和 delete。在RC、RR隔离级别下都支持。

  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。

  • 排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dyb31so1-1682170047619)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/dc1255dd-6fb0-4b19-a130-f0191cbb3b6d.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-otS8Y9F4-1682170047619)(file:///C:/Users/%E4%BB%AA/Pictures/Typedown/eee06eee-88ff-44ae-80d4-67bae4cd1edd.png)]

默认情况下,InnoDB在RR事务隔离级别运行,InnoDB使用next-key锁进行搜索和索引扫描,防止幻读。

  • 针对唯一索引进行检索时,对已存在的记录进行等值匹配时,会自动优化位行锁

  • InnoDB的行锁时针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时,就会升级位表锁。

间隙锁&临建锁

默认情况下,InnoDB在RR事务隔离级别运行,InnoDB使用next-key锁进行搜索和索引扫描,防止幻读。

  • 索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁。

  • 索引上的等值查询(非唯一缩影),向右遍历时最后一个值不满足查询需求时,next-key lock退化为间隙锁。

  • 索引上的范围查询(唯一索引)–会访问到不满足条件的第一个值为止。

间隙锁唯一目的时防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一个间隙采用间隙锁。
-------------------待更新


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部