前言

最近突发新型肺炎,本来只有七天的春节假期也因为各种封锁延长到了正月十五,在家实在闲的蛋疼便重新研究了一下Mysql数据库的相关知识,特此总结梳理一下。本文主要围绕以下几点进行:

1、Mysql的索引与引擎

2、事务隔离级别

3、Mysql的九种锁

4、几点常用规范

一、Mysql的索引与引擎

Mysql最常用的引擎是InnoDB,但还有很多种其他类型的引擎,平时最常用来与它进行比对的是MyISAM。

1、 Mysql是采用B+树作为索引存放的数据结构。B+树结构如下图所示。为什么采用这种类型呢?

因为: M阶的B+树高度不高就能存储大量数据;根据局部性原理,B+树能充分利用磁盘预读,一个叶子节点块存放磁盘读一次的容量;叶子节点用双向链表连接,极大提高了范围查找的速度。

2、Mysql数据库的索引分为两种:主键索引、普通索引 InnoDB的是聚集索引(Clustered Index),MyISAM是非聚集索引(UnClustered Index)

非聚集索引:索引与行记录分开存储。叶子节点存储数据行的地址,定位到叶子节点后再根据地址去找到具体的数据。在非聚集索引下,主键索引和普通索引的实现是一致的,都是非叶子节点存储索引列,叶子节点存储索引列和数据的指针。所以此种情况下可以没有主键索引。

非聚集索引示意图

聚集索引:主键索引与行记录存储在一起,普通索引与主键索引存储在一起。所以InnoDB的主键索引很快,但普通索引走完普通索引的B+树获取到主键索引后还要走一遍主键索引的B+树才能获取到最终的行记录。

所以聚集索引只能有一个且必须要有主键,如果用户未定义主键,则InnoDB会已第一个非空的唯一列作为聚集索引,还不行就会自己创建一个row-id。

二、Mysql的七种锁

1、自增锁

如果表字段中设置了AUTO_INCRUMENT,为保证同一个事务插入数据的递增,在插入时会触发自增锁,阻塞其他事务的插入,它是一种特殊的表级别锁。另外可以通过innodb_autoinc_lock_mode来修改配置。

2、插入意向锁(Insert intention locks)

如果插入的表中没有自增字段,则会使用插入意向锁(间隙锁的一种),即锁定要插入的索引,只要多个事物并发插入时位置不冲突就不会阻塞。

3、意向锁(Intention Locks)

InnoDB允许行级锁与表级锁共存,使用的就是意向锁。意向锁是一个表级别的锁。select * from table where id = 2 lock in share mode; 设置意向共享锁;select * from  table where id = 2 for update; 设置意向排他锁。

意向锁协议:事物要获取某些行的共享锁,需先获取意向共享锁;要获取排他锁,需先获取意向排他锁。

意向锁的共享排他锁之间不互斥,但与普通共享排他锁互斥(只有意向共享锁与普通共享锁可并行)

4、共享/排他锁(Shared and exclusive Locks)

InnoDB中共享/排他锁是标准的行级锁,互斥关系与普通的读写锁一致。

5、记录锁(Record Locks)

锁定指定的索引记录,如select * from table where id = 1 for update;就是记录锁,锁定id=1的这条索引记录

6、间隙锁(Gap Locks)

锁定索引区间,如select * from table where id between 1 and 9 for update;执行后,如果插入id=8的数据会失败。主要目的是防止写导致不可重复读,所以间隙锁也只有在隔离级别是可重复读时生效。

7、临键锁(Next-Key Locks)

可以看成记录锁与间隙锁的组合。它非锁定范围即包含索引记录也包含索引区间。临键锁也是只有在可重复读隔离级别下生效。

三、事务隔离级别

Mysql数据库有四种事务隔离级别(Oracle也是):读未提交(Read Uncommitted)、读提交(Read Committed)、可重复读(Repeated Read)、串行化(Serializable)。Mysql默认是可重复读,但一般都会改成读提交。下面针对读提交和可重复读来看看InnoDB是如何实现的。

1、首先说明一下快照读,Mysql中不带锁普通的sql语句(如select * from table where id < 2)是快照读。普通的读写锁在进行写的时候,读会被堵塞,而mysql针对此情况采用数据多版本,使得在写的时候普通读也不会阻塞。mysql在回滚段(rollback segment)中存放了undo日志,用于记录被事务操作之前事务未提交时数据的old version。这样普通读只要读老版本的数据即可。 此外还有一个redo日志,用于存放事务提交之后的数据。因为每次提交事务后都去刷磁盘,随即写效率低,所以mysql利用类似于缓存的redo日志来临时存放数据,统一往磁盘顺序写,提高吞吐量。

2、在读提交下,select /update/delete *** for update; 采用的是记录锁,即不会锁区间,只是锁匹配到的记录。如果有并发插入会导致幻读。

 3、在可重复读下,select /update/delete *** for update;如果是在唯一索引上使用唯一的查询条件,会使用记录锁,不会锁区间;而如果是范围查询,则使用间隙锁或临键锁,锁住索引记录之间的范围。在此隔离级别下,快照读在事物中第一次调用时mysql会记录一个副本,后续再有读只是从这个副本中读,不会读到之后其他事物提交的改动。

可以看到,InnoDB使用间隙锁和临键锁来避免可重复读下的幻读现象。

四、几个常用规范

1、InnoDB主键不要长了,因为每个普通索引都会存放一遍主键;InnoDB主键必须要设置,并且最好是UNSIGNED整型递增的,这样在插入行时就不会出现大量索引分裂导致数据行换位置;(参见一、2)。

2、必须把字段定义为NOT NULL并设置默认值。

3、where条件禁止用隐性类型转换、函数操作索引行,注意like的最左前缀

Mysql梳理-关于索引/引擎与锁的更多相关文章

  1. MySQL数据库InnoDB存储引擎中的锁机制

    MySQL数据库InnoDB存储引擎中的锁机制    http://www.uml.org.cn/sjjm/201205302.asp   00 – 基本概念 当并发事务同时访问一个资源的时候,有可能 ...

  2. (转)MySQL优化笔记(八)--锁机制超详细解析(锁分类、事务并发、引擎并发控制)

    当一个系统访问量上来的时候,不只是数据库性能瓶颈问题了,数据库数据安全也会浮现,这时候合理使用数据库锁机制就显得异常重要了. 原文:http://www.jianshu.com/p/163c96983 ...

  3. mysql中InnoDB存储引擎的行锁和表锁

    Mysql的InnoDB存储引擎支持事务,默认是行锁.因为这个特性,所以数据库支持高并发,但是如果InnoDB更新数据的时候不是行锁,而是表锁的话,那么其并发性会大打折扣,而且也可能导致你的程序出错. ...

  4. 重新学习MySQL数据库7:详解MyIsam与InnoDB引擎的锁实现

    重新学习Mysql数据库7:详解MyIsam与InnoDB引擎的锁实现 说到锁机制之前,先来看看Mysql的存储引擎,毕竟不同的引擎的锁机制也随着不同. 三类常见引擎: MyIsam :不支持事务,不 ...

  5. Mysql存储引擎以及锁机制

    一.常用命令 1.查看引擎(默认为InnoDB) 查看mysql提供的存储引擎:show engienes 查看mysql当前默认的存储引擎:show variables like '%storage ...

  6. 【转】MySql 三大知识点——索引、锁、事务

    索引 索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容. 索引的优点:1. 天生排序.2. 快速查找. 索引的缺点:1. 占用空间.2. 降低更新表的速度. 注意点:小表使用全表扫描更快 ...

  7. 一步一步带你入门MySQL中的索引和锁 (转)

    出处: 一步一步带你入门MySQL中的索引和锁 索引 索引常见的几种类型 索引常见的类型有哈希索引,有序数组索引,二叉树索引,跳表等等.本文主要探讨 MySQL 的默认存储引擎 InnoDB 的索引结 ...

  8. mysql的innodb 引擎 表锁与行锁

    innodb 引擎 行锁与表锁 行锁与表锁是基于索引来说的(且索引要生效) 不带索引 (表锁)要全表扫描 1. 执行select @@autocommit; 查看结果 0是不自动提交事务,1是自动提交 ...

  9. mysql基础(三)存储引擎和锁

    存储引擎的概念: 关系型数据库表是用于存储和组织信息的数据结构,可以将表理解为由行和列组成的表格,各种各样,不同的表结构意味着存储不同类型的数据,在数据的处理上也会存在着差异,对于mysql来说,它提 ...

随机推荐

  1. Node.js入门-知识整理

    目的:使用Node.js实现文件上传并将上传的文件显示到浏览器中 基本工具:Node.js,在windows下需要下载cygwin64来运行shell命令 文件:服务器模块.请求路由模块.请求处理程序 ...

  2. HDU6333 莫队+组合数学

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6333 题意: T次询问,每次询问n个苹果中最多拿m个苹果的方法数 题解: 因为T为1e5,所以直接做时间 ...

  3. 苹果笔记本修改pycharm for mac 修改字体大小

    实在是隐藏的太深了,无语

  4. MFC_对话框_访问控件_7种方法_A

    访问对话框控件的七种方法 方法一. GetDlgItem()->GetWindowText(); GetDlgItem()->SetWindowText(); 方法二. GetDlgIte ...

  5. 如何在MPlayer上支持RTSP

    http://www.live555.com/mplayer/ 请按照如下步骤 下载 "LIVE555 Streaming Media" l的库的源码, 解压后 将"li ...

  6. SQL Server内连接、左外连接、右外连接、完全连接、交叉lianjie

    数据准备: create table T1( A ) not null, B ) not null, C tinyint not null ); create table T2( B ) not nu ...

  7. OPEN GL

    https://blog.csdn.net/cdut100/article/details/45753227 https://www.jianshu.com/p/d22cf555de47 https: ...

  8. golang实现依赖注入

    golang实现依赖注入 依赖注入是软件工程中经常使用到的一种技术,它提供了一种控制反转的机制,把控制权利交给了调用方.调用方来决定使用哪些参数,哪些对象来进行具体的业务逻辑. 它有几个好处: 1 它 ...

  9. SQL Server 中数据查询注意事项

    1.查询语句不用区分大小写,而且即使每张表的表名或者列名出现大写字母,在写查询语句的时候也不用区分大小写,查询结果保持一致,所以查询语句小写即可. 2.在写查询语句的时候列名不需要带单引号,数值型的字 ...

  10. 选题Scrum立会报告+燃尽图 04

    此作业的要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8682 组长:杨天宇 组员:魏新,罗杨美慧,王歆瑶,徐丽君 组名:组长 ...