前言

最近突发新型肺炎,本来只有七天的春节假期也因为各种封锁延长到了正月十五,在家实在闲的蛋疼便重新研究了一下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. dotnet 手动解决 json 解析中不合法字符串

    如果使用 Newtonsoft Json 解析字符串,字符串里面有不清真的格式,那么默认的解析将会炸掉.如果想要自己解决字符串中的不清真格式,可以使用传入 JsonSerializerSettings ...

  2. lumen简单使用exel组件

    1.首先打开命令行,进入到lumen项目的根目录中,然后用composer下载excel组件 composer require maatwebsite/excel ~2.1.0 2.安装成功后,在bo ...

  3. spring定时器时间设置规则

    单纯针对时间的设置规则org.springframework.scheduling.quartz.CronTriggerBean允许你更精确地控制任务的运行时间,只需要设置其cronExpressio ...

  4. 百度地图addEventListener“赋值”参数

    实现点击百度地图上的覆盖物,然后获取覆盖上的属性,进而实现数据传送. var pointArray=new Array();//创建一个数组存储坐标 /*在地图上标点*/ function ShowA ...

  5. JS进阶——this绑定了谁?

    一.this的意义 二.寻找this绑定对象 经常听到这么一句话,找this只需要看谁是调用方.当函数被调用时会记录函数调用调用方式.传参包括this等各种属性.有时候this绑定对象情况太抽象,找到 ...

  6. vue项目准备工作

    1.写文档: 产品说明.工作日志.接口说明文档.数据库说明文档.项目架构说明文档等···· 例如:后台管理系统:商品的管理.店铺的管理.店铺类别管理.管理员的管理.用户管理等·····    前端渲染 ...

  7. js动态改变下拉框内容

    今天为大家分享一篇js动态设置select下拉菜单的默认选中项实例,具有很好的参考价值,希望对大家有所帮助. 代码实例如下: <!DOCTYPE html> <html lang=& ...

  8. 兄弟们,你们天天吊打面试官,面试官很难受啊。 metasploit免S客户端

    metasploit生成的exe文件很小,但是免杀效果不行, 找了很多资料, 只有生成c语言shellcode,然后c#重新编译, 这种免杀效果,挺让人满意的 首先需要生成客户端,客户端使用了ngro ...

  9. SpringBoot中SpringMVC的自动配置以及扩展

    一.问题引入 我们在SSM中使用SpringMVC的时候,需要由我们自己写SpringMVC的配置文件,需要用到什么就要自己配什么,配置起来也特别的麻烦.我们使用SpringBoot的时候没有进行配置 ...

  10. java高并发梳理