首页 > 数据库 >Mysql索引和锁的使用

Mysql索引和锁的使用

时间:2022-08-22 11:33:51浏览次数:47  
标签:插入 事务 记录 Mysql 索引 使用 级别 id

B+树索引的使用


  1. B+树索引在空间和时间上都有代价,所以没事儿别瞎建索引。
  2. B+树索引适用于下边这些情况:
    • 全值匹配
    • 匹配左边的列
    • 匹配范围值
    • 精确匹配某一列并范围匹配另外一列
    • 用于排序
    • 用于分组
  3. 在使用索引时需要注意下边这些事项:
    • 只为用于搜索、排序或分组的列创建索引
    • 为列的基数大的列创建索引
    • 索引列的类型尽量小
    • 可以只对字符串值的前缀建立索引
    • 只有索引列在比较表达式中单独出现才可以适用索引
    • 为了尽可能少的让聚簇索引发生页面分裂和记录移位的情况,建议让主键拥有AUTO_INCREMENT属性。
    • 定位并删除表中的重复和冗余索引
    • 尽量使用覆盖索引进行查询,避免回表带来的性能损耗。

MVCC的注意点

我们前边说过,对于使用Inno+DB存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们创建的表中有主键或者非NULL的UNIQUE键时都不会包含row_id列):

  • trx_id:每次一个事务对某条聚簇索引记录进行改动时,都会把该事务的事务id赋值给trx_id隐藏列。
  • roll_pointer:每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。
  1. 对于使用READ UNCOMMITTED隔离级别的事务来说,由于可以读到未提交事务修改过的记录,所以直接读取记录的最新版本就好了;
  2. 对于使用SERIALIZABLE隔离级别的事务来说,设计InnoDB的大叔规定使用加锁的方式来访问记录(加锁是啥我们后续文章中说哈);
  3. 对于使用READ COMMITTED和REPEATABLE READ隔离级别的事务来说,都必须保证读到已经提交了的事务修改过的记录,也就是说假如另一个事务已经修改了记录但是尚未提交,是不能直接读取最新版本的记录的,核心问题就是:需要判断一下版本链中的哪个版本是当前事务可见的。
  4. READ COMMITTD、REPEATABLE READ这两个隔离级别的一个很大不同就是:生成ReadView的时机不同,READ COMMITTD在每一次进行普通SELECT操作前都会生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作前生成一个ReadView,之后的查询操作都重复使用这个ReadView就好了。

MVCC 进行非阻塞读和写, 效率非常高.

工作面试老大难 - 锁

采用MVCC方式的话,读-写操作彼此并不冲突,性能更高,采用加锁方式的话,读-写操作彼此需要排队执行,影响性能。

共享锁和独占锁:

  • 共享锁,英文名:Shared Locks,简称S锁。在事务要读取一条记录时,需要先获取该记录的S锁。
  • 独占锁,也常称排他锁,英文名:Exclusive Locks,简称X锁。在事务要改动一条记录时,需要先获取该记录的X锁。
    锁定读:
    对读取的记录加S锁:
    SELECT ... LOCK IN SHARE MODE;
    对读取的记录加X锁:
    SELECT ... FOR UPDATE;
  • 意向共享锁,英文名:Intention Shared Lock,简称IS锁。当事务准备在某条记录上加S锁时,需要先在表级别加一个IS锁。
  • 意向独占锁,英文名:Intention Exclusive Lock,简称IX锁。当事务准备在某条记录上加X锁时,需要先在表级别加一个IX锁。

对于MyISAM、MEMORY、MERGE这些存储引擎来说,它们只支持表级锁,而且这些引擎并不支持事务,所以使用这些存储引擎的锁一般都是针对当前会话来说的。

InnoDB中的表级锁

表级别的S锁、X锁

在对某个表执行SELECT、INSERT、DELETE、UPDATE语句时,InnoDB存储引擎是不会为这个表添加表级别的S锁或者X锁的。

另外,在对某个表执行一些诸如ALTER TABLE、DROP TABLE这类的DDL语句时,其他事务对这个表并发执行诸如SELECT、INSERT、DELETE、UPDATE的语句会发生阻塞,同理,某个事务中对某个表执行SELECT、INSERT、DELETE、UPDATE语句时,在其他会话中对这个表执行DDL语句也会发生阻塞。这个过程其实是通过在server层使用一种称之为元数据锁(英文名:Metadata Locks,简称MDL)东东来实现的,一般情况下也不会使用InnoDB存储引擎自己提供的表级别的S锁和X锁。

表级别的IS锁、IX锁

当我们在对使用InnoDB存储引擎的表的某些记录加S锁之前,那就需要先在表级别加一个IS锁,当我们在对使用InnoDB存储引擎的表的某些记录加X锁之前,那就需要先在表级别加一个IX锁。IS锁和IX锁的使命只是为了后续在加表级别的S锁和X锁时判断表中是否有已经被加锁的记录,以避免用遍历的方式来查看表中有没有上锁的记录。

表级别的AUTO-INC锁

采用AUTO-INC锁,也就是在执行插入语句时就在表级别加一个AUTO-INC锁,然后为每条待插入记录的AUTO_INCREMENT修饰的列分配递增的值,在该语句执行结束后,再把AUTO-INC锁释放掉。

也可以采用一个轻量级的锁,在为插入语句生成AUTO_INCREMENT修饰的列的值时获取一下这个轻量级锁,然后生成本次插入语句需要用到的AUTO_INCREMENT列的值之后,就把该轻量级锁释放掉,并不需要等到整个插入语句执行完才释放锁。

InnoDB 中的行级锁

我们来看看都有哪些常用的行锁类型:

Record Locks

Gap Locks

我们说MySQL在REPEATABLE READ隔离级别下是可以解决幻读问题的,解决方案有两种,可以使用MVCC方案解决,也可以采用加锁方案解决。但是在使用加锁方案解决时有个大问题,就是事务在第一次执行读取操作时,那些幻影记录尚不存在,我们无法给这些幻影记录加上正经记录锁。gap锁的作用仅仅是为了防止插入幻影记录的而已。

Next-Key Locks:

有时候我们既想锁住某条记录,又想阻止其他事务在该记录前边的间隙插入新记录,所以设计InnoDB的大叔们就提出了一种称之为Next-Key Locks的锁,官方的类型名称为:LOCK_ORDINARY,我们也可以简称为next-key锁。

Insert Intention Locks:

我们说一个事务在插入一条记录时需要判断一下插入位置是不是被别的事务加了所谓的gap锁(next-key锁也包含gap锁,后边就不强调了),如果有的话,插入操作需要等待,直到拥有gap锁的那个事务提交。但是设计InnoDB的大叔规定事务在等待的时候也需要在内存中生成一个锁结构,表明有事务想在某个间隙中插入新记录,但是现在在等待。设计InnoDB的大叔就把这种类型的锁命名为Insert Intention Locks,官方的类型名称为:LOCK_INSERT_INTENTION,我们也可以称为插入意向锁。

隐式锁

那如果一个事务首先插入了一条记录(此时并没有与该记录关联的锁结构),然后另一个事务:

  • 立即使用SELECT ... LOCK IN SHARE MODE语句读取这条记录,也就是在要获取这条记录的S锁,或者使用SELECT ... FOR UPDATE语句读取这条记录,也就是要获取这条记录的X锁,该咋办?
    如果允许这种情况的发生,那么可能产生脏读问题。
  • 立即修改这条记录,也就是要获取这条记录的X锁,该咋办?
    如果允许这种情况的发生,那么可能产生脏写问题。

情景一:对于聚簇索引记录来说,有一个trx_id隐藏列,该隐藏列记录着最后改动该记录的事务id。那么如果在当前事务中新插入一条聚簇索引记录后,该记录的trx_id隐藏列代表的的就是当前事务的事务id,如果其他事务此时想对该记录添加S锁或者X锁时,首先会看一下该记录的trx_id隐藏列代表的事务是否是当前的活跃事务,如果是的话,那么就帮助当前事务创建一个X锁(也就是为当前事务创建一个锁结构,is_waiting属性是false),然后自己进入等待状态(也就是为自己也创建一个锁结构,is_waiting属性是true)。

通过上边的叙述我们知道,一个事务对新插入的记录可以不显式的加锁(生成一个锁结构),但是由于事务id这个牛逼的东东的存在,相当于加了一个隐式锁。别的事务在对这条记录加S锁或者X锁时,由于隐式锁的存在,会先帮助当前事务生成一个锁结构,然后自己再生成一个锁结构后进入等待状态。

标签:插入,事务,记录,Mysql,索引,使用,级别,id
From: https://www.cnblogs.com/success-zh/p/16612249.html

相关文章

  • MySQL数据库的四种隔离级别
    一、首先介绍几个概念:1,脏读:又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改但是还未提交,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改并提交,这就导致了......
  • ModelBox开发体验:使用YOLOv3做口罩检测
    摘要:本案例将在ModelBox中使用YOLOv3模型,实现一个简单的口罩检测应用本文分享自华为云社区《ModelBox开发体验Day05开发案例-使用YOLOv3做口罩检测》,作者:孙小北。本案......
  • Mybatis 懒加载使用及源码分析
    Mybatis懒加载的使用什么是懒加载?懒加载的意思就是在使用的时候才去加载,不使用不去加载,相反的就叫饥饿加载或者立即加载。懒加载在Mybatis中一般是存在与联合查询的情况,......
  • Stream流-传统集合的多步变量代码和使用Stream流方式进行过滤
    Stream流说的Stream便容易想到I/OStream而实际上谁规定“流”就一定是Io流呢?在java8中得益于Lambda所带来的函数式编程引入了一个全新的Stream概念用于解决已有集合......
  • 如何使用.NET 6的IHostedService和BackgroundService?
    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进。本章是《定制ASPNET6.0框架系列文章》的第七篇。本......
  • 深入理解 Spring 事务:入门、使用、原理
    大家好,我是树哥。Spring事务是复杂一致性业务必备的知识点,掌握好Spring事务可以让我们写出更好地代码。这篇文章我们将介绍Spring事务的诞生背景,从而让我们可以更清......
  • Apache HttpClient 5 使用详细教程
    点赞再看,动力无限。微信搜「程序猿阿朗」。本文Github.com/niumoo/JavaNotes和未读代码博客已经收录,有很多知识点和系列文章。超文本传输协议(HTTP)可能是当今......
  • 使用Pytorch手写ViT — VisionTransformer
    《TheAttentionisallyouneed》的论文彻底改变了自然语言处理的世界,基于Transformer的架构成为自然语言处理任务的的标准。尽管基于卷积的架构在图像分类任务中仍然是......
  • 使用@arcgis/core本地部署ArcGIS API for JS
    一、简介@arcgis/core官方文档ArcGISAPIforJavaScript是WebGIS开发中非常重要的前端JS库,是浏览器端调用ArcGIS功能所使用的库。如ArcmapPro中所使用的创建要素,编辑......
  • java线上问题跟踪工具Arthas的第一次使用
    Arthas是一款线上监控诊断产品,通过全局视角实时查看应用load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异......