【转】MySql 三大知识点——索引、锁、事务
索引
索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容。
索引的优点:1. 天生排序。2. 快速查找。
索引的缺点:1. 占用空间。2. 降低更新表的速度。
注意点:小表使用全表扫描更快,中大表才使用索引。超级大表索引基本无效。
索引从实现上说,分成 2 种:聚集索引和辅助索引(也叫二级索引或者非聚集索引)
从功能上说,分为 6 种:普通索引,唯一索引,主键索引,复合索引,外键索引,全文索引。
详细说说 6 种索引:
- 普通索引:最基本的索引,没有任何约束。
- 唯一索引:与普通索引类似,但具有唯一性约束。
- 主键索引:特殊的唯一索引,不允许有空值。
- 复合索引:将多个列组合在一起创建索引,可以覆盖多个列。
- 外键索引:只有InnoDB类型的表才可以使用外键索引,保证数据的一致性、完整性和实现级联操作。
- 全文索引:MySQL 自带的全文索引只能用于 InnoDB、MyISAM ,并且只能对英文进行全文检索,一般使用全文索引引擎(ES,Solr)。
- 注意:主键就是唯一索引,但是唯一索引不一定是主键,唯一索引可以为空,但是空值只能有一个,主键不能为空。
另外,InnoDB 通过主键聚簇数据,如果没有定义主键且没有定义聚集索引, MySql 会选择一个唯一的非空索引代替,如果没有这样的索引,会隐式定义个 6 字节的主键作为聚簇索引,用户不能查看或访问。
简单点说:
设置主键时,会自动生成一个唯一索引,如果之前没有聚集索引,那么主键就是聚集索引。
没有设置主键时,会选择一个不为空的唯一索引作为聚集索引,如果还没有,那就生成一个隐式的 6 字节的索引。
MySql 将数据按照页来存储,默认一页为 16kb,当你在查询时,不会只加载某一条数据,而是将这个数据所在的页都加载到 pageCache 中,这个其实和 OS 的就近访问原理类似。
MySql 的索引使用 B+ 树结构。在说 B+ 树之前,先说说 B 树,B 树是一个多路平衡查找树,相较于普通的二叉树,不会发生极度不平衡的状况,同时也是多路的。
B 树的特点是:他会将数据也保存在非页子节点。
看图可知:
而这个特点会导致非页子节点不能存储大量的索引。
而 B+ Tree 就是针对这个对 B tree 做了优化。如下图所示:
我们看到,B+ Tree 将所有的 data 数据都保存到了叶子节点中,非也子节点只保存索引和指针。
我们假设一个非页子节点是 16kb,每个索引,即主键是 bigint,即 8b,指针为 8b。那么每页能存储大约 1000 个索引(16kb/ 8b + 8b).
而一颗 3 层的 B+树能够存储多少索引呢?如下图:
大约能够存储 10 亿个索引。通常 B+ 树的高度在 2-4 层,由于 MySql 在运行时,根节点是常驻内存的,因此每次查找只需要大约 2 -3 次 IO。可以说,B+ 树的设计,就是根据机械磁盘的特性来进行设计的。
知道了索引的设计,我们能够知道另外一些信息:
MySql 的主键不能太大,如果使用 UUID 这种,将会浪费 B+ 树的非叶子节点。
MySql 的主键最好是自增的,如果使用 UUID 这种,每次插入都会调整 B+树,从而导致页分裂,严重影响性能。
那么,如果项目中使用了分库分表,我们通常都会需要一个主键进行 sharding,那怎么办呢?在实现上,我们可以保留自增主键,而逻辑主键用来作为唯一索引即可。
锁机制
关于 Mysql 的锁,各种概念就会喷涌而出,事实上,锁有好几种维度,我们来解释一下。
- 类型维度
共享锁(读锁 / S 锁)
排它锁(写锁 / X 锁)
- 类型细分:
- 意向共享锁
- 意向排他(互斥)锁
- 悲观锁(使用锁,即 for update)
乐观锁(使用版本号字段,类似 CAS 机制,即用户自己控制。缺点:并发很高的时候,多了很多无用的重试)
- 锁的粒度(粒度维度)
表锁
页锁(Mysql BerkeleyDB 引擎)
行锁(InnoDB)
- 锁的算法(算法维度)
Record Lock(单行记录)
Gap Lock(间隙锁,锁定一个范围,但不包含锁定记录)
Next-Key Lock(Record Lock + Gap Lock,锁定一个范围,并且锁定记录本身, MySql 防止幻读,就是使用此锁实现)
- 默认的读操作,上锁吗?
- 默认是 MVCC 机制(“一致性非锁定读”)保证 RR 级别的隔离正确性,是不上锁的。
可以选择手动上锁:select xxxx for update (排他锁); select xxxx lock in share mode(共享锁),称之为“一致性锁定读”。
使用锁之后,就能在 RR 级别下,避免幻读。当然,默认的 MVCC 读,也能避免幻读。
既然 RR 能够防止幻读,那么,SERIALIZABLE 有啥用呢?
防止丢失更新。例如下图:
这个时候,我们必须使用 SERIALIZABLE 级别进行串行读取。
最后,行锁的实现原理就是锁住聚集索引,如果你查询的时候,没有正确地击中索引,MySql 优化器将会抛弃行锁,使用表锁。
事务
事务是数据库永恒不变的话题, ACID:原子性,一致性,隔离性,持久性。
四个特性,最重要的就是一致性。而一致性由原子性,隔离性,持久性来保证。
原子性由 Undo log 保证。Undo Log 会保存每次变更之前的记录,从而在发生错误时进行回滚。
隔离性由 MVCC 和 Lock 保证。这个后面说。
持久性由 Redo Log 保证。每次真正修改数据之前,都会将记录写到 Redo Log 中,只有 Redo Log 写入成功,才会真正的写入到 B+ 树中,如果提交之前断电,就可以通过 Redo Log 恢复记录。
然后再说隔离性。
隔离级别:
- 未提交读(RU)
- 已提交读(RC)
- 可重复读(RR)
- 串行化(serializable)
每个级别都会解决不同的问题,通常是3 个问题:脏读,不可重复读,幻读。一张经典的图:
这里有个注意点,关于幻读,在数据库规范里,RR 级别会导致幻读,但是,由于 Mysql 的优化,MySql 的 RR 级别不会导致幻读:在使用默认的 select 时,MySql 使用 MVCC 机制保证不会幻读;你也可以使用锁,在使用锁时,例如 for update(X 锁),lock in share mode(S 锁),MySql 会使用 Next-Key Lock 来保证不会发生幻读。前者称为快照读,后者称为当前读。
原理剖析:
RU 发生脏读的原因:RU 原理是对每个更新语句的行记录进行加锁,而不是对整个事务进行加锁,所以会发生脏读。而 RC 和 RR 会对整个事务加锁。
RC 不能重复读的原因:RC 每次执行 SQL 语句都会生成一个新的 Read View,每次读到的都是不同的。而 RR 的事务从始至终都是使用同一个 Read View。
RR 不会发生幻读的原因: 上面说过了。
那 RR 和 Serializble 有什么区别呢?答:丢失更新。本文关于锁的部分已经提到。
MVCC 介绍:全称多版本并发控制。
innoDB 每个聚集索引都有 4 个隐藏字段,分别是主键(RowID),最近更改的事务 ID(MVCC 核心),Undo Log 的指针(隔离核心),索引删除标记(当删除时,不会立即删除,而是打标记,然后异步删除);
本质上,MVCC 就是用 Undo Log 链表实现。
MVCC 的实现方式:事务以排它锁的方式修改原始数据,把修改前的数据存放于 Undo Log,通过回滚指针与数据关联,如果修改成功,什么都不做,如果修改失败,则恢复 Undo Log 中的数据。
多说一句,通常我们认为 MVCC 是类似乐观锁的方式,即使用版本号,而实际上,innoDB 不是这么实现的。当然,这不影响我们使用 MySql。
【转】MySql 三大知识点——索引、锁、事务的更多相关文章
- MySql 三大知识点——索引、锁、事务
1. 索引 索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容. 索引的优点:1. 天生排序.2. 快速查找.索引的缺点:1. 占用空间.2. 降低更新表的速度. 注意点:小表使用全表扫描 ...
- MySql 三大知识点——索引、锁、事务(转)
1. 索引 索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容. 索引的优点:1. 天生排序.2. 快速查找.索引的缺点:1. 占用空间.2. 降低更新表的速度. 注意点:小表使用全表扫描 ...
- MySql 三大知识点——索引、锁、事
作者:莫那鲁道原文:http://thinkinjava.cn/2019/03/16/2019-03-16-mysql/ 1. 索引 索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容. ...
- MySql 三大知识点,索引、锁、事务,原理分析
1.索引 索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容. 索引的优点:1. 天生排序,2. 快速查找. 索引的缺点:1. 占用空间,2. 降低更新表的速度. 注意点:小表使用全表扫描 ...
- MySQL数据库_索引_事务_优化 _锁_存储引擎_存储过程_CAP
##一.基础 ## * 插入 INSERT INTO table_name ( field1, field2,...fieldN ) ...
- mysql innodb存储引擎 锁 事务
以下内容翻译自mysql5.6官方手册. InnoDB是一种通用存储引擎,可平衡高可靠性和高性能.在MySQL 5.6中,InnoDB是默认的MySQL存储引擎.除非已经配置了不同的默认存储引擎, ...
- mysql 在线加索引 锁表
mysql在线修改表结构大数据表的风险与解决办法归纳 - 王滔 - 博客园 http://www.cnblogs.com/wangtao_20/p/3504395.html MySQL 加索引 加字段 ...
- MySQL数据库之索引、事务、存储引擎详细讲解
一.索引 1.1 索引的概念 索引是一个排序的列表,存储着索引值和这个值所对应的物理地址 无须对整个表进行扫描,通过物理地址就可以找到所需数据 (数据库索引类似书中的目录,通过目录就可以快速査找所需信 ...
- mysql 多列唯一索引在事务中select for update是不是行锁?
在表中有这么一索引 UNIQUE KEY `customer_id` (`customer_id`,`item_id`,`ref_id`) 问1. 这种多列唯一索引在事务中select for upd ...
随机推荐
- sql server 存储过程和视图的区别
视图 要把视图看做是一张表,包含了一张表的部分数据或者多个表的综合数据,视图的使用和普通表一样: 视图建立并存储在服务器,有效减少网络数据流量,提高安全性: 视图中不存放数据,数据依然存放在视图引用的 ...
- 五十九.大数据、Hadoop 、 Hadoop安装与配置 、 HDFS
1.安装Hadoop 单机模式安装Hadoop 安装JAVA环境 设置环境变量,启动运行 1.1 环境准备 1)配置主机名为nn01,ip为192.168.1.21,配置yum源(系统源) 备 ...
- Linux中查看和修改分区的uuid方便挂载使用
查看硬盘UUID: 两种方法: ls -l /dev/disk/by-uuid blkid /dev/sda1 修改分区UUID: 1.修改分区的UUID Ubuntu 使用 uuid命令 生成新的u ...
- [svn]查看,删除svn账号
1.查看svn账号 ll ~/.subversion/auth/svn.simple 随便打开一个文件 这是保存的对应地址的svn账号和密码,都是明文的 win路径:C:\Users\ysk\AppD ...
- 2016"百度之星" - 初赛(Astar Round2A)1005 BD String(HDU5694)——找规律、字符串对称、分治
分析:按照题目所给的意思每次处理得到的新的字符串都是具有高度对称性的,举个例子,如题目所给的第三个字符串,最中间的是B然后两边分散开去,一边是B的话另外一边关于这个中心对称的那个位置一定是D,反过来同 ...
- Raspberry Pi 4B Web服务器配置
目录 1. 安装nginx 2. 安装PHP 3. 修改nginx配置文件 4. 安装MariaDB数据库 参考资料1:树莓派4B安装PHP7.3 + Nginx + MySQL 教程 参考资料2:[ ...
- puppeteer学习笔记合集
官方英文版API入口(如果你英文好的话):https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md. 汉化版API入口(网上有 ...
- Mysql 原理以及常见mysql 索引等
## 主键 超键 候选键 外键 (mysql数据库常见面试题) 数据库之互联网常用架构方案 数据库之互联网常用分库分表方案 分布式事务一致性解决方案 MySQL Explain详解 ## 数据库事务的 ...
- mysql服务器变量、缓存及索引
服务器变量 注意:其中有些参数支持运行时修改,会立即生效:有些参数不支持,且只能通过修改配置文件,并重启服务器程序生效:有些参数作用域是全局的,且不可改变:有些可以为每个用户提供单独(会话)的设置. ...
- H5本地存储详解
H5之前存储数据一般是通过 cookie ,但是 cookie 存的数据容量比较少.H5 中扩充了文件存储能力,可存储多达 5MB 的数据.现在就实际开发经验来对本地存储 ( Storage ) 的使 ...