MySQL

数据库基础知识

为什么要使用数据库

数据保存在内存里

优点:存取速度快

缺点:不能永久保存

数据保存在文件里

优点:数据永久保存

缺点:1)速度比内存操作满,频繁的IO操作 2)查询数据不方便

数据保存在数据库中

  1. 数据永久保存
  2. 使用SQL语句,查询方便效率高
  3. 管理数据方便

什么是SQL

结构化查询语言,(StructuredQueryLanguage)简称SQL,是一种数据库查询语言

作用:用于存取数据、查询、更新和管理关系型数据库系统

什么是MySQL

MySQL是一个关系型数据库管理系统,在WEB应用方面,MySQL是最好的RDBMS(关系型数据库管理系统)

数据库的三大范式是什么

第一范式:每个列都不可以在拆分

第二范式:在第一范式的基础上:非主键列完全依赖于主键,而不能是依赖于之间的一部分(希望消除表中冗余的列,一个主键不能关联多条数据)

第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键(依然是希望消除表中冗余的列,消除表中主键的传递关系,即不能有列间接依赖主键)

在设计数据库结构时,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能。事实上我们经常会因为性能而妥协数据库的设计。

MySQL的binlog有几种录入格式,有什么区别

有三种格式 statement、row和mixed

  • statement模式下,每一条会修改数据的sql都会记录在binlog中。不需要记录每一行的变化,减少了binlog的日志量,节约了IO,提高性能。由于SQL的执行是有上下文的,因此保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制
  • row级别下,不记录sql语句上下文相关信息,仅保存哪条记录被修改,记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动,因此这种模式的文件保存的信息太多,日志量太大。
  • mixed,一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row

数据类型

MySQL有哪些数据类型

整性类型

  • tinyInt:很小的整数,8位二进制
  • smallint:小的整数,16位二进制
  • mediumint:中等大小的整数,24位二进制
  • int(integer):普通大小的整数,32位二进制
  • bigint:大整形:64位二进制

整形类型,包括tinyint,smallint,mediumint,int、bigint,分别表示1字节、2字节、3字节、4字节、8字节整数。任何整数类型都可以加上UNSIGNED属性,表示这个数据是无符号的,即非负整数

整数类型长度:整数类型可以被指定长度,例如int(11),表示长度为11的int类型。长度在大多数场景是没有意义的,他不会限制值的合法范围,只会影响现实字符的个数,而且需要和UNSIGNEDZEROFILL属性配合使用他才有意义

例如一个UNSIGNEDZEROFILL int(5),用户插入12,会显式00012

小数类型

  • float:单精度浮点数
  • double:双精度浮点数
  • decimal(m,d):压缩严格的定点数

实型类型,包括float,double,decimal。decimal可以用于存储比bigint还大的整形,能存储精确的小数,而float和double是有取值范围的,并支持使用标准的浮点进行近似计算。

计算float和double相比decimal效率更高一些,decimal你可以理解成是用字符串进行处理。

日期类型

  • year:YYYY 1901~2155
  • time:HH:MM:SS
  • date:YYYY-MM-DD
  • datetime:YYYY-MM-DD HH:MM:SS
  • timestamp:YYYY-MM-DD HH:MM:SS

尽量使用timestamp,空间效率高于datetime,用整数保存时间戳通常不方便处理。如果需要存储微秒,可以使用bigint

文本、二进制类型

  • char(m):m位0~65535之间的整数
  • varchar(m):m位0~65535之间的整数
  • tinyblob:允许长度0~255字节
  • blob:允许长度0~65535字节
  • mediumblob:允许长度0~167772150
  • longblob:允许长度0~4294967295
  • tinytext:允许长度0~255字节
  • text:允许长度0~65535字节
  • mediumtext:允许长度0~167772150
  • longtext:允许长度0~4294967295
  • varbinary(m):允许长度0~m个字节长度的变长字节字符串
  • binary(m):允许长度0~m字节的定长字节字符串

字符串类型,包括varchar,char,text,blob。varchar用于存储可变长字符串,它比定长类型更节省空间

varchar使用额外1或者2个字节存储字符串长度,列长度小于255字节使,使用1字节表示,否则使用2字节表示。

varchar存储的内容超出设置的长度时,内容会被截断

char是定长的,根据定义的字符串长度分配足够的空间。

char会根据需要使用空格进行填充方便比较

char适合存储很短的字符串,或者所有值都接近同一个长度

char存储的内存超出设置的长度时,内容同样会被截断

使用策略

对于经常变更的数据来说,char比varchar更好,因为char不容易产生碎片

对于非常短的列,char比varchar在存储空间上更有效率

使用时要注意只分配需要的空间,更长的列排序时会消耗更多内存。尽量避免使用text/blob类型,查询时会使用临时表,导致严重的性能开销

引擎

MySQL存储引擎,MyISAM与InnoDB的区别

存储引擎:MySQL中的数据、索引以及其他的对象是如何存储的,是一套文件系统的实现。

常用的引擎有

InnoDB引擎:InnoDB提供了对数据库ACID事务的支持,还提供了行级锁和外键的约束。它的设计的目标就是处理大数据容量的数据库系统。

MyIASM引擎(原本MySQL的默认引擎):不提供事务的支持,也不支持行级锁和外键

MEMORY引擎:所有的数据都在内存中,数据的处理速度快,但是安全性不高

MyISAM和InnoDB的区别

MyISAM InnoDB
存储结构 每张表被存放在三个文件:frm-表格定义,MYD(MYDATE)-数据文件、MYI(MYIndex)-索引文件 所有的表都保存在同一个数据文件idb中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2G
存储空间 MyISAM可被压缩,存储空间较小 InnoDB的表需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引
可移植性、备份及恢复 由于MyISAM的数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可以单独针对某个表进行操作 免费的方案是可以拷贝数据文件、备份binlog,或者使用mysqldump,在数据量达到几十G就相对比较差了
文件格式

数据和索引是分别存放的,数据:.MYD,索引.MYI

数据和索引是集中存储的,.ibd
记录存储顺序 按记录插入顺序保存 按主键大小有序插入
外键 不支持 支持
事务 不支持 支持
锁支持(锁是避免资源争用的一个机制,MySQL锁对用户几乎是透明的) 表级锁定 行级锁定、表级锁定、锁定粒度小并发能力高
SELECT MyISAM更优
INSERT、UPDATE、DELETE InnoDB更优
selectcount(*) MyISAM更优,因为MyISAM内部维护了一个计数器,可以直接调取
索引的实现方式 B+树索引,MyISAM是堆表 B+树索引,InnoDB是索引组织表
哈希索引 不支持 支持
全文索引 支持 不支持
表主键 支持一张没有任何主键的表 如果没有指定主键,会指定一个唯一字段,作为主键索引,如果还没有就自动生成一个用户不可见的主键作为索引

MyISAM和InnoDB两者的应用场景:

1)MyISAM管理非事务表。他提供高速存储和检索,以及全文搜索的能力。如果应用总需要执行大量的SELECT查询,那么MyISAM是更好的选择

2)InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高用户并发操作的性能。

实际场景中,针对具体问题需要具体分析,一般而言可以遵循以下几个问题:

  • 数据库是否有外键
  • 是否需要事务支持
  • 是否需要全文索引
  • 数据库经常使用什么样的查询模式?在写多读少的应用中还是InnoDB插入性能更稳定,在并发情况下也能基本稳定,如果是对读取速度要求比较快的应用还是选MyISAM
  • 数据库的数据有多大大尺寸倾向于使用InnoDB,因为事务日志,故障恢复

InnoDB引擎的4大特性

  • 插入缓冲
  • 二次写
  • 自适应哈希索引
  • 预读

索引

什么是索引

索引是一种特殊的文件(InnoDB引擎中的数据表上索引是表空间的一部分),它们包含着对数据表里所有记录的引用指针

索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询,更新数据库表中的数据。索引的实现通常使用B树以及其变种B+树

更通俗的说,索引就相当于目录。为了方便查找书中的内容,通过对内容建立索引形成目录。索引是一个文件,它是要占据物理空间的。

MySQL官方对索引的定义:索引(index)是帮助MySQL高效获取数据的数据结构

索引有哪几种类型

主键索引:数据列不允许重复,不允许为NULL,一个表只能有一个主键

唯一索引:数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引

  • 可以通过ALTER TABLE table_name ADD UNIQUE(column); 创建唯一索引
  • 可以通过ALTER TABLE table_name ADD UNIQUE(column1,column2);创建唯一组合索引

普通索引:基本的索引类型,没有唯一性的限制,允许为NULL值。

  • 可以通过ALTER TABLE table_name ADD INDEX(column);
  • 可以通过ALTER TABLE table_name ADD INDEX(column1,column2,column3);
  • 全文索引:是目前搜索引擎使用的一种关键技术。可以通过 ALTER TABLE table_name ADD FULL TEXT(column);创建全文索引

索引的数据结构

索引的数据结构和具体存储引擎的实现有关,再MySQL中使用较多的索引有

Hash索引,B+索引等,而我们经常使用的InnoDB存储索引实现为:B+树索引。对于哈希索引来说,底层的数据结构就是哈希表,因此再绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能快;其余大部分场景,建议选择BTree索引

1)B树索引MySQL通过存储引擎取数据,基本上90%的人用的就是InnoDB了,按照实现方式分,InnoDB的所有类型目前只有两种:B树和Hash索引。B树索引是MySQL数据库中使用频繁的索引类型,基本所有存储引擎都支持

B树索引。通常我们说的索引一般指的就是B树索引(实际是使用B+树实现的,因为再查看表索引是,MySQL一律打印BTree,所以简称B树索引)

查询方式:

(B树方式,每页中存储n个数据和n+1个指针)

主键索引区:PI(关联保存的数据的地址)按主键查询(指向下一页的指针)

普通索引区:SI(关联的id的地址,然后再到达上面的地址)。所以按主键查询,速度快(该页的数据)

B+树性质

  • n棵子树的节点包含n个关键字,不用来保存数据而是保存数据的指针
  • 所有叶子节点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子节点本身根据关键字的大小自小而大顺序链接(B+树除了非叶子节点外的所有节点都不存储数据,只存储指向下一个节点的指针,叶子节点只存储数据,并且由一个双向链表链接。这种设计相较于B树,可以再存储相同数据量的时候,树的层级更小,查询效率更高。因为每一页的大小都相同,指针的大小一般小于数据,一个节点即是一页,只存储指针可以存储的更多
  • 所有的非叶子节点都可以看成是索引部分,节点中仅包含其子树中的关键字
  • B+树中,数据对象的插入和删除仅在叶子节点上进行
  • B+树有两个头指针,一个是树的根节点,一个是小关键码的叶子节点

2)哈希索引

类似于数据结构中简单实现的hash表,当我们在mysql中使用哈希索引时,主要就是通过hash算法将数据库中的字段数据转换成定长的hash值,这与这条数据的行指针一并存入hash表对应位置

索引设计的原则

  1. 适合索引的列是出现在where子句中的列,或者链接子句中指定的列
  2. 基数较小的列,索引效果较差,没有必要在此列建立索引
  3. 使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间(前缀索引
  4. 不要过度使用索引。索引需要额外的磁盘空间,并且降低些操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索引越多,这个时间就会越长。所以纸包装需要的索引有利于查询即可。

创建索引的原则

  1. 最左前缀原则:组合索引使用非常重要的原则,mysq会一直向右匹配直到遇到(>,<,between,like)就停止匹配,如果建立的组合索引是(a,b,c,d) ,查询子句,a=1 and b=1 and c>1 and d=1,那么这种情况只会使用索引到c为止,d是用不到索引的。
  2. 较频繁作为查询条件的字段才去创建索引
  3. 更新频繁的字段不适合创建索引
  4. 选择区分度比较强的字段创建索引(例如性别,只有男和女,创建索引的用处不大)
  5. 尽量扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,只需要修改原来的索引即可
  6. 定义有外键的数据一定要建立索引
  7. 对于那些查询中很少涉及的列,重复值比较多的列不要建立索引
  8. 对于定义为text,blob,image、bit的数据不要建立索引

创建索引的三种方法

1)在创建表的时候创建

CREATE TABLE user(
    KEY idx_user_a_b(a,b)

UNIQUE KEY idx_user_unique(unique)

FULLTEXT KEY idx_user_full(full)
)

2)

ALTER TABLE user ADD INDEX(column)

3)

CREATE INDEX idx_user_a ON user(a);

使用索引查询一定能提高查询的性能吗

通常,通过索引查询数据一定比全表扫描要快,但是我们要注意他付出的代价。

索引需要空间来存储,也需要定其维护,每当有记录在表中增减或者索引列被修改时,索引本身也会被修改,甚至被重构。这意味着每次写操作时,会进行多次IO操作。因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。使用索引查询不一定能提高查询性能

百万级别或者以上的数据如何进行删除

  1. 先删除索引
  2. 然后删除其中的无用数据
  3. 删除完成后重新创建索引
  4. 比直接删除数据要快很多

前缀索引

语法:INDEX(column(len)),比如使用密码的前十位建立索引,不设置长度的话,默认是用全部内容建立索引。

前提:前缀的标识度高,比如用密码的前十位即可区分全部密码。假设某个字段,遵循某一个格式,前面的字符都一样,用前缀索引不能区分,就不能使用前缀索引。、

难点:在于选择前缀的长度,我们可以利用 SELECT COUNT(*) /COUNT(DISTINCT LEFT(column,len));通过调整len,在len最短的时候获取最高的匹配程度,接近1即可。例如,8位匹配程度 75 ,9位100,10位 100,我们就可以使用9位字符作为前缀索引。

InnoDB支持hash索引吗

InnoDB文档明确指出,是不支持hash索引的,但是,实际上InnoDB存储引擎支持的哈希索引是自适应的,InnoDB存储引擎会根据表的使用,自动为表生成hash索引,我们无法干预。也就是我们无法自己创建hash索引,但是InnoDB会自己自动化的创建hash索引

什么是最左前缀原则,什么是最左匹配原则

在创建多列索引时,根据业务需求,where子句中使用最频繁的一列放在最左边,MySQL会在查询时,一直向右匹配直到遇到范围查询(>,<,between,like)就会停止匹配

B树和B+树的区别

在B树中,你可以将键和值存放在内部节点和叶子节点;但是B+树中,内部节点都是键,没有值,叶子节点同时存放键和值。

B+树的叶子节点有一条双向链表相连,而B树的叶子节点各自独立。

使用B树的好处

B树的结构特征,使得我们在频繁访问特定数据(靠近根节点的数据)时,效率非常高,这种特性使得B树在特定数据重复多次查询的场景中更加高效

使用B+树的好处

由于B+树的内部节点只存放键,不存放值,因此一次读取,可以在内存页中获得更多的键,有利于快速的缩小查找范围(本质上就是,内部节点中存储的都是键,而键所占的字节数比值的少,所以同一块数据中可以存放更多页,可以降低树的层数,整体上来说,查询效率就高了),b+树的叶子节点由一条双向链表相连,因此当需要进行一次全数据遍历的时候,B+树只需要找到最小的节点,然后遍历链表即可,而B树则需要对树的每一次进行遍历,需要花费更长的时间。

为什么使用B+树而不是B树

已知,由于结构问题,一个B+树的节点存储的键比B树多,导致B+树的高度更低,所以一次B+树可以查找的关键字也就越多,相对的IO读写的次数也就降低了,而IO读写次数时影响检索效率最大的因素

B+树的查找效率更加稳定,因为值都在叶子节点上所以每次查找都会找到叶子节点,查找的效率一致,而B树可能在内部节点就找到值

B+树在进行全表遍历时,只需要找到最小的值,然后遍历链表即可,B树需要遍历所有的节点

增删节点时,效率更高。因为B+树的叶子节点包含所有关键字,并且是有序的链表结构存储,可以很好的提高增删效率。

Hash索引和B+树有什么区别和优劣呢

首先要直到hash索引和b树索引的底层原理。

Hash索引底层是,hash表,每次查找,将键的hash值算出,直接获得数据,B树底层是多路平衡查找树,每次都要从根节点开始搜索,查找到叶子节点方可以获得所查键值。

即可得以下不同:

Hash索引进行等值查询更快,但是无法进行范围查询

因为通过数据存储不是线性存储,而是根据hash值存储,根据一个hash值无法获得多个数据。所以不支持范围查询,而B树,所有左子树的键都是小于父节点的,所有右子树的键都是大于父节点的,所以支持范围查询。

hash索引不支持排序,

hash索引不支持模糊查询,多列索引和最左前缀匹配

hash索引任何时候都避免不了回表查询,B树在使用聚簇索引、覆盖索引时可以只通过一次索引完成查询

hash索引虽然进行等值匹配的效率比B树高,但是可能存在哈希冲突的情况,不稳定,性能不能预测。而B+树的查询效率稳定,且B+树的高度比较低,查询效率较高且稳定。

所以一般情况下直接使用B+树索引就可以获得稳定且较好的查询速度。而不需要使用hash索引

数据库为什么使用B+树而不是B树

B树只适合随机检索,而B+树同时支持随机检索和顺序检索

B+树的空间利用率更高,可以减少I/O次数,磁盘读写代价更低。

B+树的查询效率更加稳定。B树搜索有可能会在非叶子节点结束,越靠近根节点的记录时间越短。B+树所有的记录都在叶子节点,所以所有记录的查找路径相同,所以B+树查找效率稳定

B+树的每一个叶子节点都用一个双向链表链接,所以进行全表扫描的时候,只需要找到最小的那个节点,然后遍历链表即可。

什么是聚簇索引,何时使用聚簇索引与非聚簇索引

聚簇索引:将数据和索引存储在一块,找到索引也就找到了数据

非聚簇索引:将数据和索引分开存储,索引结构的叶子节点是指向了数据的对应行,MyISAM通过key_buffer把索引缓冲到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key_buffer命中时,速度慢的原因

InnoDB中,在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查询(回表查询),非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引,辅助索引的叶子节点存储的不再是行的物理位置,而是主键值。

非聚簇索引一定会用到回表查询吗?

不一定,非聚簇索引有,联合索引,唯一索引和前缀索引等,联合索引中存储的的复合的多条字段的值以及主键的值,如果查找的数据包含在这几条数据中,就不需要使用主键进行回表查询。

联合索引是什么,为什么需要注意联合索引中的顺序

MySQL支持使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引的顺序使用,否则,后面的索引会失去效果。

具体原因为,MySQL使用索引时需要索引有序,假设现在建立了‘name,age,school’的联合索引,那么索引的排序为:先按照name排序,如果name相同,则按照age排序,如果age也相同就按照school排序,

当进行查询时,此时索引仅仅按照name有序,因此必须先使用name进行等值匹配,之后得到的字段在按照age有序,以及类推,所以建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。

MyISAM索引和InnoDB索引的区别

  • InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引
  • InnoDB索引的主键索引的叶子节点存储着行数据,因此主键索引非常高效
  • MyISAM索引的叶子节点存储的是行数据地址,需要子寻址一次才能得到数据
  • InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效

事务

什么是数据库事务

数据库事务是一个不可分割的数据库操作序列也是数据库并发控制的基本单位其执行结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。

事务的四大特性ACID

原子性:

事务是最小的执行单位,不允许分割。即事务中的一组操作,要么同时成功,要么同时失败。

一致性:

事务操作前后,数据保持一致,即多个事务多同一个数据读取的结果是相同的。

隔离性:

并发访问数据库时,一个用户的事务不湖北其他事务所干扰,各并发事务之间是相互独立的。

持久性:

一个事务提交以后,它对数据库中的数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

什么是脏读,不可重复读、幻读

脏读

事务A更新了一个数据,还没有提交,然后事务B读取了这个数据,此时事务B读取的就是脏数据,如果事务A因为某种原因发生了回滚,事务B就会出现错误,也就是脏读

不可重复读

一个事务对同一个数据读取了两次,两次读取到的结果不一致,这可能是因为两次查询中间插入了一个事务更新原有的数据。

幻读:在一个事务的两次查询中数据的数量不一致,第一次查询出了三条记录,而第二次查出了7条,凭空出了4条,就好像出了幻觉一样,所以叫幻读。发生这种情况一般是,两次查询中,另一个事务插入了几行新的数据。

什么是事务的隔离级别,MySQL的默认隔离级别是什么

为了达到事务的四大特性,数据库定义了4中不同的事务隔离级别,从低到高依次是,读未提交(READ-UNCOMMITTED),读已提交(READ-COMMITTED),可重复读(REPEATABLE-READ),串行化(SERIALIZABLE)

脏读 不可重复度 幻读
读未提交 T T T
读已提交 F T T
可重复读 F F T
串行化 F F F
  • 读未提交:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、不可重复读和幻读
  • 读已提交:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍可能发生
  • 可重复读:对同一字段的多次读取保证结果是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但是不可以阻止幻读
  • 串行化:最高的隔离级别,完全服从ACID,所有事务依次执行,脏读、不可重复读和幻读都不会出现。

MySQL默认采用可重复读,Oracle默认采用读已提交

事务隔离机制的实现基于锁机制的并发调度。其中并发调度使用的是MVCC(多版本并发控制),通过保存修改的旧版本信息俩支持并发一致性读和回滚等特性。

事务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的市MVCC(多版本并发控制),通过保存修改的旧版本信息来支持并发一致性读和回滚等特性

因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别市读已提交;但是InnoDB存储引擎默认使用可重复读,并不会有任何性能损失。

InnoDB存储引擎在分布式事务的情况下一般会用到可串行化的隔离级别

对MySQL的锁了解吗

当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁就是这样的一个机制。

隔离级别和锁的关系

在读未提交级别下,读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突。

在读已提交级别下,读操作需要加共享锁,但是在语句执行完后释放共享锁。

在可重复读级别下,读操作需要加共享锁,且在事务提交之前不能释放共享锁,也就是必须等待事务执行完毕后才能释放共享锁。

可串行化是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。

按照锁的粒度划分数据库锁有哪些,锁机制与InnoDB锁算法

在关系型数据库中,可以按照锁的粒度将锁分为,表锁,行锁,页锁。

MyISAM支持表锁

InnoDB支持行锁和表锁

行级锁

行级锁是数据库中锁定粒度最小的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作之间的冲突。虽然其加锁粒度最小,但是其加锁开销最大。行级锁分为共享锁和排他锁。

特点:开销大,加锁慢,会出现死锁;粒度最小,出现锁冲突的可能性最低,并发度高

表级锁

表级锁是MySQL锁定粒度最大的一种锁,表示对当前操作的整张表都加锁,实现较为简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MyISAM和InnoDB都支持表级锁定。表级锁定分为共享锁和排他锁

特点:开销小,加锁快,不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度低

页级锁

页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表锁速度快,但是冲突多,行级锁,冲突少但是加锁慢。所以有页锁,一次锁定一页的数据。

特点:开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般。

从锁的类别上分MySQL有哪些锁

从锁的类别上来缩,有共享锁(读锁),排他锁(写锁);

共享锁(读锁):当用户要进行数据的读取时,可以对数据加上共享锁,共享锁可以同时加上多个,允许多个事务进行读,但是所有的事务都不能写。

排他锁(写锁): 当用户要进行数据的写入时,对数据加上排他锁。排他锁只允许加一个,他和其他的排他锁和共享锁都互斥,即加了排他锁的事务可以读可以写,其他的事务既不能读,也不能写。

InnoDB存储引擎的锁的算法

  • Record lock(记录锁):即行锁,对数据表中的行记录加锁
  • Cap lock(间隙锁):锁定一个范围,不包括记录本身
  • Next-Key lock(临键锁):即行锁+间隙锁,锁定一个间隙,包括记录本身

相关知识点:

  1. InnoDB 对于行的查询使用临键锁
  2. 临键锁为了解决幻读问题
  3. 当查询的索引含有唯一属性的时候,将临键锁降级为记录锁
  4. 间隙锁设计的目的是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生

什么是死锁,怎么解决

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象

解决方法

  1. 如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。
  2. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生的概率
  3. 对于非常容易产生死锁的业务部分,可以尝试使用升级锁定粒度,通过表级锁来减少死锁产生的概率
  4. 如果业务处理不好可以使用分布式事务锁或者使用乐观锁。

数据库的悲观锁和乐观锁

悲观锁:假定一定会发生冲突,屏蔽一切有可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制

乐观锁:假定一定不会发生冲突,只在提交操作时检查是否违反了数据完整性。在修改数据的时候把事务锁起来,通过version的方式进行锁定。实现方式:使用版本号机制或者CAS算法实现

两种锁的使用场景不同,当写操作比较少,读操作频繁的时候,使用乐观锁会降低加锁解锁的开销,提高数据库整体的吞吐量。但是当写操作比较多的情况,乐观锁反而会降低性能,这个时候应该使用悲观锁

视图

为什么要使用视图,什么是视图

为了提高复杂SQL语句的复用性和表操作的安全性,MySQL数据库关系系统提供了视图特性。所谓视图,本质上是一种虚拟表,在物理上不存在,其内容与真实存在的表相似,包含一系列带有名称的列和行数据。但是视图并不在数据库中以储存的数据值形式存在。行和列数据来自定义视图的查询所引用的基本表,并且在具体引用视图时动态生成。

视图使开发者只关心感兴趣的某些特定数据和所负责的特定任务,只能看到视图中所定义的数据,而不是视图所引用表中的数据,从而提高了数据库中数据的安全性

视图有哪些特点

  • 视图的列可以来自不同的表,是表的抽象和在逻辑意义上建立的新关系
  • 视图是由基本表(实表)产生的表(虚表)
  • 视图的建立和删除不影响基本表
  • 对视图内容的更新操作直接影响基本表
  • 当视图来自多个基本表时,不允许添加和删除数据。视图的操作包括创建视图,查看视图,删除视图和修改视图

视图的使用场景有哪些

视图根本用途:简化sql查询,提高开发效率。如果说还有另外一个用途那就是兼容老的表结构

  • 重用SQL语句
  • 简化复杂的SQL操作,在编写查询后,可以方便的重用它而不必知道它的基本查询细节;使用表的组成部分而不是整个表。
  • 保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限。
  • 更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。

视图的优缺点

优点:

  1. 查询简单化。视图能简化用户的操作
  2. 数据安全性。视图使用户能以多种角度看待同一数据,能够对机密数据提供安全保护
  3. 逻辑数据独立性。视图对重构数据库提供了一定程度的逻辑独立性

缺点:

  1. 性能。数据库必须把视图的查询转化为对基本表的查询,如果这个视图是由一个复杂的多表查询所定义的,那么即使视图是一个简单查询,数据库也把它变成一个复杂的结合体,需要花费一定的时间。
  2. 修改限制。当用户视图修改视图的某些行时,数据库必须把它转化为对基本表的某些行的修改。事实上,当从视图中插入或者删除时,情况也是这样。对于简单视图来说,这是很方便的,但是,对于比较复杂的视图,可能时不可修改的。

这些视图有如下特征

  1. 有UNIQUE等集合操作符的视图
  2. 有GROUP BY子句的视图
  3. 有诸如AVG\SUM\MAX等聚合函数的视图
  4. 使用DISTINCT关键字的视图
  5. 链接表的视图

什么是游标

游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。用户可以通过对游标注意获取记录并赋值给主变量,交由主语言进一步处理。

存储过程和函数

什么是存储过程,有哪些优缺点

存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需要创建一次,以后再该程序的执行中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单次SQL语句执行要快。

优点:

  1. 存储过程是预编译过的,执行效率高
  2. 存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯
  3. 安全性高,执行存储过程需要有一定权限的用户。
  4. 存储过程可以重复使用,减少数据库开发人员的工作量。

缺点:

  1. 调试麻烦,但是用PL/SQL Developer调试很方便!弥补了这个缺点。
  2. 移植问题,数据库端代码当然是与数据库相关的。但是如果做工程性项目,基本不存在移植性问题。
  3. 重新编译问题,因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时,受影响的存储过程、包将需要重新编译
  4. 如果再一个程序系统中大量的使用了存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,后如果用乎想维护该系统很困难。

触发器

什么是触发器,触发器的使用场景有哪些

触发器是用户定义在关系表上的一类由事件驱动的特殊存储过程。触发器是指一段代码,当触发某个事件时,自动执行这些代码。

使用场景

  • 可以通过数据库中的相关表实现级联更改。
  • 实时监控某张表中的某个字段的更改而需要做出相应的处理。
  • 例如可以生成某些业务的编号

MySQL中有哪些触发器

  • Before Insert
  • After Insert
  • Before Update
  • After Update
  • Before Delete
  • After Delete

常用SQL语句

数据库定义语言DDL(Data Definition Language)CREATE 、DROP、ALTER 主要为以上操纵即对逻辑结构等有操作的,其中包括表结构,视图和索引。

数据查询语句DQL(Date Query Language) SELECT 即查询操作,各种简单查询,链接查询都属于DQL。

数据操纵语言DML(Date Manipulation Language)INSERT UPDATE DELETE 主要为以上操作即对数据进行操作的,对应上面所说的查询操作,DQL与DML共同构建了多数初级程序员常用的增删改查操作。查询是增删改查中较为特殊的一种,被单独划分出来为DQL语句。

数据控制功能DCL(Date Control Language) GRANT,REVOKE,COMMIT,ROLLBACK主要为以上操作,即对数据库安全性完整性等有操作的,可以简单理解为权限控制等。

超键、候选键、主键、外键分别是什么

超键:在关系中能标识元组的属性集称为关系模式的超键。一个属性可以作为一个超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。唯一标识元组的属性集称为超键

候选键:没有冗余元素的超键

主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值。主键是一个选中的候选键

外键:在一个表中存在的另一个表的主键称为此表的外键。

SQL约束有哪几种

  • NOT NULL 用于控制一个字段的内容一定不能为空
  • UNIQUE 控制字段内容不能重复,一个表允许有多个Unique约束
  • PRIMARY KEY 也是用于控件字段内容不能重复,且非空,但它在一个表只允许出现一个
  • FOREIGN KEY 用于预防破坏表之间链接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
  • DEFAULT 设置默认值
  • CHECK 用于控制字段的值范围

六种关联查询

交叉连接(CROSS JOIN):

获得两个表的笛卡尔积,结果集会很大,没有意义

内连接 (INNER JOIN)

查出两个表的交集,内连接分为三种,等值连接,不等值连接和自连接

外连接(LEFT JOIN /RIGHT JOIN)

LEFT JOIN 以左表为主体,县查询出左表,按照ON后的关联条件匹配右表,没有匹配到的用NULL填充

RIGHT JOIN 相反

联合查询(UNION /UNION ALL)

把两次或者多次查询的结果集合并,UNION前的结果为基准,需要注意的是联合查询你的列数要相等,UNION相同的记录会合并,UNIONALL不会,UNION的执行效率高于UNIONALL

全连接(FULL JOIN)

MySQL不支持全连接,但是可以使用LEFT JOIN 和 RIGHT JOIN 联合使用

SELECT * FROM A LEFT JOIN B ON A.id = B.id UNION SELECT * FROM A RIGHT JOIN B ON A.id = B.id

其实就是两个表的左连接和右连接合并

MySQL中in和exists区别

mysql中的in语句是把外表和内标做hash连接,而exists语句是对外表做loop循环,每次循环在对内表进行查询。

in

确定给定的值是否与子查询或列表中的值相匹配。in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快。

exists

将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE 或者 FALSE)来决定主查询数据结果是否得到保留。

性能

  1. 如果查询的两个表大小相当,那么用in和exists差别不大
  2. 如果两个表中一个较小,一个是大表,在子查询表大的用exists,子查询表小的用in
  3. not in和not exists 如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比 not in快

varchar与char的区别

char的特点

char表示的是定长字符串,长度是固定的;如果插入数据的长度小于char的固定长度时,则用空格填充。

因为长度固定,所以存取的速度要比varchar快很多,甚至能快50%,但正因为其长度固定,所以会占据多余的空间,是空间换时间的做法。

对于char来说,最多能存放的字符个数为255,和编码无关

varchar的特点

varchar表示可变长字符串,长度是可变的;

插入的数据是多长就按照多长来存储;

varchar在存取方面和char相反,它存取慢,因为长度不固定,但是正因为如此,不占据多余的空间,是时间换空间的做法;

对于varchar来说,多能存放的字符个数为65532.

总之,结合性能角度看,char更快,结合节省磁盘资源空间的角度(varchar更小),具体情况还需要具体来设计数据库才是妥当的做法

varchar(50) 中50的涵义

最多存放50个字符,varchar(50)和(200)存储hello所占空间一样,但后者在排序时会消耗更多内存,因为order by column 采用fixed_length 计算column长度(memory引擎也一样),在早期MySQL版本中,50代表字节数,现在代表字符数

int(20)中20的涵义

是指显示字符的长度。20表示最大显示宽度,但是任然占4字节存储,存储范围不变;

不影响内部存储,只是影响带zerofill定义的int时,前面多补多少个0,易于报表展示

MySQL中int(10)和char(10)以及varchar(10)的区别

int(10) 中的10表示显示的数据的长度,不是存储数据的大小;char(10)和varchar(10) 表示存储数据的长度,即表示存储多少个字符。

char(10)存储数据是定长的,也就是即使存储的数据长度没有到10,也会通过补0到10位,而varchar(10)是不定长的,存入的数据是多少位就是多少位,但是最长为10位

FLOAT和DOUBLE的区别是什么

FLOAT类型数据可以存储最多8位十进制数,并在内存中占4字节

DOUBLE类型数据可以存储最多18位十进制数,并在内存中占8字节

drop、delete与truncate的区别

三者都表示删除,但是三者有一些差别:

Delete Truncate Drop
类型 属于DML 属于DDL 属于DDL
回滚 可以回滚 不可回滚 不可回滚
删除内容 表结构还在,删除表的全部或者一部分数据行 表结构还在删除表中的所有数据 从数据库中删除表,所有的数据行,索引和权限也会被删除
删除速度 删除速度慢,需要逐行删除 删除速度快 删除速度快

SQL优化

如何定位及优化SQL语句的性能问题

对于低性能的SQL语句的定位,重要且有效的方法就是使用执行计划,MySQL提供了explain命令来查看语句的执行计划。我们知道,不管是哪种数据库,或者哪种数据库引擎,在对一条SQL语句进行执行的过程中都会做很多相关的优化,对于查询语句,最重要的优化方式就是使用索引而执行计划,就是显示数据库引擎对于SQL语句执行的详细情况,其中包含了是否使用索引,使用什么索引,使用的索引的相关信息等

执行过程:

id:表示一个查询中各个子查询的执行顺序;

  1. id相同执行顺序由上至下
  2. id不同,id值越大优先级越高,越先被执行
  3. id为null时表示一个结果集,不需要使用它查询,常出现在包含union等查询语句中

select_type:每个子查询的查询类型

table:查询的数据表,当从衍生表中查数据时会显示x表示对应的执行计划id

partitions:表分区、表创建的时候可以指定通过哪个列进行表分区

type(可以看到有没有走索引)访问类型

  • all 扫描全表数据
  • index 遍历索引
  • range 索引范围查找
  • ref 查找非唯一性索引,返回匹配某一条件的多条数据。属于精确查找、数据返回可能是多条
  • eq_ref 查找唯一性索引,返回的数据至多一条。属于精确查找
  • const 查找主键索引,返回的数据至多一条(0或者1条)。 属于精确查找
  • system const的特例,仅返回一条数据的时候。

possible_keys 可能使用的索引,不是一定会用,查询涉及到的字段上弱存在索引,则该索引将被列出来。当该列为NULL时就要考虑当前是SQL是否需要优化了。

key 显示MySQL在查询中实际使用的索引,若没有索引,显示为NULL。

key_length 索引长度

ref 表示上述表的连接匹配田间,即哪些列或者常量被用于查找索引累上的值rows返回估算的结果集数目

extra 额外信息

  • Using index 表示使用覆盖索引
  • Using where 表示使用where子句来过滤结果集
  • Using filesort 使用了文件排序,使用非索引列进行排序时出现,非常消耗性能,尽量优化
  • Using temporary 使用了临时表

SQL的生命周期

  1. 应用服务器和数据库服务器建立一个连接
  2. 数据库进程拿到一个SQL请求
  3. 数据库解析SQL生成执行计划、执行
  4. 读取数据到内存并进行逻辑处理
  5. 通过步骤1的连接,将数据返回个应用服务器
  6. 关闭连接释放资源

超大分页怎么处理

超大分页一般指,我们一张数据库表中有10000000+条记录,我们执行select * from table where age >20 limit 1000000,10这种查询。会将前1000000条记录全表load然后再全部丢弃,只取十条,这样当然很慢。一般从以下两个方面解决

  • 数据库层面,改用 select s.* from table s ,(select id from table where age >20 limit 1000000,10) t wher s.id= t.id;这种方式虽然也load了1000000条数据,但是由于索引覆盖,要查询的所有字段都在索引中,所以速度会很快
  • 从需求角度看,我们可以减少这种请求,不允许做直接跳转到几百万页后的具体的某一页,只允许再某个范围内跳转。

*重要

经我实验,select * from user ,也就是没有where子句且没有指定要查找的列时,默认全表扫描,效率很低(这个时候表里只有 id 主键索引)。

select id from user,这个sql语句没有where子句,possible_key 为null,但是实际上使用了id主键索引(相比上面那种查找select *,不需要回表查询,效率更高)

select * from user where id= 1 /select id from user where id = 1 这两个sql语句中的possible_key不为空且,key也实际使用了 索引。

得出结论,存在where子句时,如果条件字段有索引,则使用索引查询。不存在where子句但是查询的数据列存在索引时,也会使用索引查询。当查询数据列为*且没有where子句时走全表扫描。

慢查询日志

用于记录执行时间超过某个临界值的sql日志,用于快速定位慢查询,为我们的优化做参考

关心过业务系统里面的sql耗时吗,统计过慢查询吗,对慢查询都怎么进行优化

慢查询都怎么优化过

在业务系统中,除了使用主键进行的查询,其他的我都会在测试库上测试其耗时。慢查询的优化首先要搞明白慢的原因是什么?是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大?一般优化都是针对这三个方面进行优化。

首先分析语句,看看是否是load了额外的数据,可能查询了多余的行并且抛弃掉了,可能是加载了许多结果不需要的列,对语句进行分析以及重写

使用explain分析语句的执行计划,然后获得查询语句使用的索引的情况之后,修改语句或者修改索引,使得语句可以尽可能的命中索引。

如果对语句和索引已经无法在进行优化,可以考虑表中大数据量是否太大,如果是可以进行横向或者纵向的分表

为什么要尽量设定一个主键

主键是数据库表中确保数据库行在整张表唯一性的保障,即使业务上本张表没有主键,也建议添加一个自增长的主键,设定了主键之后,在后续的增删改查的时候可能更快速以及确保操作数据范围安全

主键使用自增ID还是UUID

推荐使用自增ID,不要使用UUID

因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断的向后排列即可,如果是UUID,由于到来的ID和原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。

总之,在数据量大一些的情况下,用自增主键性能会好一些。

对于主键是聚簇索引,如果没有主键,InnoDB会选择一个唯一键来作为聚簇索引,如果没有唯一键,会生成一个隐式的主键。

字段为什么要定义为NOT NULL

  1. 如果不设置NOT NULL的话,NULL是列的默认值,如果不是本身需要的话,尽量就不要使用NULL,默认值为NULL可能导致,聚合函数不准确,=失效等问题。

  2. 使用NULL带来更多的问题,比如索引、索引统计、值计算更加复杂,如果使用索引,就要避免列设置成NULL,当数据中NULL的占比较多时,索引会失效

  3. 如果是索引列,会带来的存储空间的问题,需要额外的特殊处理,还会导致更多的存储空间占用

  4. 对于稀疏数据有更好的空间效率,稀疏数据指的是很多值为NULL,只有少数行的列有非NULL值的情况

如果要存储用户的密码散列,应该使用什么字段进行存储

密码散列,盐,用户身份证号等固定长度的字符串应该使用char而不是varchar,因为这些数据的长度都是固定的,用定长字符串就可以保存,定长字符串的存取效率还比varchar好。

优化查询过程中的数据访问

访问数据太多导致查询性能下降,应该去确认应用程序是否检索大量超过需求的数据,可能太多行或者列,确认MySQL服务器是否在分析大量不必要的数据行

例如

查询不需要的数据:使用limit解决

多表关联返回全部列:指定列名解决

总是返回全部列:解决方法,避免使用select *,重复查询相同的数据。解决办法:可以缓存数据,下次直接读取缓存是否在扫描额外的记录。

使用explain进行分析,如果发向查询需要扫描大量的数据,但是只返回少数的行,可以通过如下技巧去优化:

使用索引覆盖扫描,把所有的列都放到索引中,这样存储引擎不需要回表获取对应行就可以返回结果。

改变数据库表的结构,修改数据表范式

重写sql语句。

COUNT() 优化

count(*)约等于count(1)>count(主键)>count(非主键)

SQL语句优化的一些方法

  1. 对查询进行优化,应该尽量避免全表扫描,首先考虑在where及order by涉及的列上建立索引。
  2. 应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描
  3. 应尽量避免在where子句中使用!=或者<>操作符,否则引擎将放弃使用索引而进行全表扫描
  4. 应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描
  5. 应尽量避免在where子句中使用in 和 not ,否则会导致全表扫描
  6. ‘%x’这种格式的模糊查询也会导致全表扫描
  7. 应该尽量避免在where子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择
  8. 应尽量避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描
  9. 应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描
  10. 不要再where子句中的‘=’左边进行函数、算法运算,或者其他表达式运算,否则系统将可能无法正确使用索引

MySQL中的MVCC

在MySQL中MVCC是在InnoDB存储引擎中得到支持的,InnoDB为每行记录都实现了三个隐藏字段:

  • 6字节的事务ID(DB_TRX_ID)
  • 7字节的回滚指针(DB_ROLL_PTR)
  • 隐藏的ID(DB_ROW_ID)

6字节的事务ID用来标识该行为所述的事务,7字节的回滚指针需要了解以下InnoDB的事务模型

InnoDB的事务相关概念

为了支持事务,InnoDB引入了下面几个概念

  • redo log,就是保存执行SQL语句到一个指定的log文件中,当MySQL 执行recovery时重新执行redolog中记录的SQL操作即可。当客户端执行每条SQL(更新语句)时,redolog会被首先写入log buffer;当客户端执行COMMIT命令时,log buffer 中的内容会被视情况刷新到磁盘,redo log在磁盘上作为一个独立的文件存在,即InnoDB 的log文件。总结:redolog就是为了保证我们在进行脏页刷新发生错误时,进行数据恢复,从而保证事务的持久性。将脏页刷新到磁盘出现错误时,通过磁盘中的redo log文件恢复。
  • undo log,与redo log 相反,undo log是为回滚而用,具体内容就是copy事务前的数据库内容(行)到undo buffer 在适合的时间把undo buffer中的内容刷新到磁盘,undo buffer 与redo buffer一样,也是环形缓冲,但当缓冲满的时候,undo buffer 中的内容会被刷新到磁盘中,与redo log不同的是,磁盘上不存在单独undo log文件,所有的undo log均存放在主ibd数据文件中。作用:提供回滚和MVCC。就是当事务提交出现错误时,提供数据回滚。
  • rollback segment:回滚段这个概念来自Oracle的事务模型,在InnoDB中,undolog被划分为多个段,具体某行的undo log就保存在这个段中,称为回滚段,可以认为undo log和回滚段是同一意思
  • 隔离级别

行的更新过程

1、初始数据行

我们知道,数据表隐藏着三个字段,1、事务ID,2、回滚指针,3、ROW_ID(没有设置主键时有)

2、事务一更改该行的各字段的值

当事务一更改数据行时,会进行以下操作

  1. 用排他锁锁定该行
  2. 记录redo log
  3. 把该行修改前的值Copy到undo log
  4. 修改当前行,事务ID自增,回滚指针指向上一条undo log 数据行的地址

3、事务二修改该行的值

与事务一相同,此时的undo log中有两条记录,并且通过回滚指针连在一起。

因此,如果undo log 一直不删除,则会通过当前记录的回滚指针回溯到该行创建时的初始内容,InnoDB中存在purge线程,它会查询哪些比现在最老的活动事务还早的undolog,并删除他们,从而保证undo log文件不会无限增长

4、事务提交

当事务正常提交时InnoDBB只需要更改事务状态为COMMIT即可,不需要做其他额外的工作,而RollBcak则稍微复杂一点,需要根据当前回滚指针从undo log中找出事务修改前的版本,并恢复。如果事务影响的行非常多,回滚则可能会变的效率不高。

事务级别

更新是一个事务过程,在InnoDB中,查询也是一个事务,只读事务。当读写事务并发访问同一行数据时,能读到什么数据则依赖事务级别。

1)读未提交

读事务直接读取主记录,无论新事务是否完成

2)读已提交

读提交时,读事务每次都读取undo log中最近的版本,因此两次对同一字段的读可能读到不同的数据(不可重复读),但能保证每次都读到最新的数据

3)可重复读

每次都读取指定的版本,这样保证不会产生(不可重复读),但是可能读不到最新的数据

4)可串行化

锁表,读写相互阻塞,使用较少

MVCC

上述更新前建立 undo log,根据各种策略读取时非阻塞就是MVCC,undo log中的行就是MVCC中的多个版本

InnoDB中MVCC的实现方式

  • 事务以排他锁的形式修改原始数据
  • 把修改前的数据存放于undo log,通过回滚指针与主数据关联
  • 修改成功(事务提交)啥都不做,失败则从undo log中回滚数据

MVCC实现 读已提交和可重复读的方法

面经

KYLO的数据库知识总结相关推荐

  1. 国考最热岗位报录比20602:1?还是数据库知识挑战赛适合我

    什么?212万人报名2022年国考? 最热门的西藏阿里地区某岗位 报录比竟然高达20602:1? 千军万马过独木桥 都是勇士 当然,网上国考气氛组也不能少 有人对两万里挑一的人充满了好奇 有人担心考试 ...

  2. Sybase数据库技术,数据库恢复---分享Sybase数据库知识(博客文章索引@51cto)

    Sybase数据库技术,数据库恢复 分享Sybase数据库知识 博客文章列表,更新时间:2014-12-14 Sybase数据库技术,数据库恢复 站点地图 最新文章 ASE使用with ignore_ ...

  3. 学习C++项目——数据库知识学习(主从原理,分离配置,远程工具只是了解,都没有实现)

    学习数据库知识 一.思路和学习方法   本文学习于:B站平台UP主 IT 小当家,学习 MySQL 数据库,如里面加以自己的一些学习复现和理解,如有侵权会进行删除.学习Oracle以后也可以参考之前学 ...

  4. 学习C++项目——mysql 数据库知识学习(关于 mysql 8.0 版以后基础部分学习)

    学习数据库知识 一.思路和学习方法   本文学习于:B站平台UP主 IT 小当家,学习 MySQL 数据库,里面仅仅用于自己学习,进行复现,并加以自己的一些学习过程和理解,如果有侵权会删除.因为 Or ...

  5. Android 数据库知识回顾

    一.前言 二.效果预览 ​三.数据库与框架的基础使用 (1)第一道:原生数据库 (2)第二道:LitePal框架 (3)第三道:GreenDao框架 四.总结 五.Demo地址 六.内容推荐 一.前言 ...

  6. 即将实习的应届毕业生 学习java SpringMVC 数据库 知识总结

    即将实习的应届毕业生 学习java SpringMVC 数据库 知识总结 1.Java语言的优点: 1)Java是纯面向对象语言 2)与平台无关性,一次编译到处运行 3)Java提供了狠多内置类库 4 ...

  7. 肝了三天的四万字MySQL数据库知识总结

    mysql数据库知识梳理总结 即使再小的帆也能远航~ 一. 目录 数据库介绍 数据库安装 SQL概念 DDL DML操作表中的数据 DQL单表查询 数据库备份和还原 DCL 数据库表的约束 表与表之间 ...

  8. Sybase数据库技术,数据库恢复---分享Sybase数据库知识(博客文章索引)

    Sybase数据库技术,数据库恢复 分享Sybase数据库知识 博客文章列表,更新时间:20141218 Sybase数据库技术,数据库恢复 » 站点地图 最新文章 ASE使用with ignore_ ...

  9. oracle (+)的,数据库知识(SQL+ORACLE)

    数据库知识(SQL+ORACLE) 概述 安易系统的SQL以及ORACLE使用相关 一.SQL SQL工具 数据备份以及还原 1.SQL工具         企业管理器:         查询分析 ...

  10. 嵌入式数据库知识概括

    嵌入式数据库知识概况 嵌入式数据库 Derby SQLite H2 总结 嵌入式数据库 嵌入式数据库(Embedded Database)简介: 从软件角度来说,数据库分类为两种: ①第一种:数据库服 ...

最新文章

  1. python可视化窗口制作一个摇骰子游戏_使用python制作一个抽奖小游戏——骰子游戏...
  2. ajax post 参数说明
  3. 【宽搜】XMU 1039 Treausure
  4. C++Study 指针详解
  5. JavaScript 工作原理之十一-渲染引擎及性能优化小技巧 1
  6. 计算器的程序代码java_求用JAVA编写的计算器程序代码
  7. 最大流自用模板(例题:HDU1532)
  8. 第十八届绵竹年画节开幕 大巡游展示清末年画《迎春图》场景
  9. jquery中的css() animate() width()的都可以运用相对值
  10. golang学习的点点滴滴:异常处理 defer, panic, recover
  11. phpMyAdmin创建数据库无权限解决方案
  12. opencv入门—播放AVI视频
  13. 一个破解压缩包密码的软件——ziperello
  14. cad刷新快捷键_CAD快捷键大全清单,送给每一位CAD初学者,非常实用的干货
  15. 1012-RPA与目标使用者
  16. 人工智能在人力资源行业中的应用
  17. 【观察】亚信科技:“飞轮效应”背后的数智化创新“延长线”
  18. 因果,因果推断,因果关系是什么?
  19. 绝对值编码器常见的故障有哪些 如何处理
  20. JavaScript中绑定事件监听函数的通用方法[ addEvent() ]

热门文章

  1. Spring Guide:Securing a Web Application(中文大概意思)
  2. nifi集群_NiFi安装(单机+集群)
  3. 科技感人工智能PPT模板推荐
  4. PyQt5快速入门教程4-QtDesigner设计登录界面
  5. wsimport简单实现WebService
  6. 解决solidworks导入stl文件就卡死的问题
  7. 正方教务系统对服务器的要求,正方软件教务系统功能介绍.docx
  8. Ubuntu下录制视频并在PPT上放映
  9. Janusgraph事务
  10. Android系统镜像文件