目录

存储引擎

说一说mysql有哪些存储引擎及它们之间有什么区别?

索引

谈一下索引?

索引有哪些优缺点?

索引的使用场景?

B树和B+树的区别?

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

索引的数据结构?

为什么不用hash索引?

B-Tree索引的限制?

索引设计的原则?

百万级别或以上的数据如何删除?

Mysql中索引有哪几种?

聚簇索引和非聚簇索引(二级索引)的区别和联系?

概念

二级索引如何和聚簇索引交互?

全文索引(FULL-TEXT INDEX)

前缀索引

什么是左前缀(匹配)原则?

索引覆盖

什么是联合索引?为什么要注意联合索引中列的顺序?

事务

什么是事务?事务的四大特性介绍一下

SQL执行的过程?

谈谈事务的实现原理?(redo log+undo log+锁、MVCC)

什么是脏读、幻读、不可重复读、丢失修改?

一致性读(consistent read)

MySql中的四个隔离级别?

什么是MVCC(多版本并发控制)?

谈谈快照读和当前读?

MySql如何防止幻读?

MySql中的锁

Mysql中有哪几种锁?

共享锁(S)和排它锁(X)

意向锁(Intension Locks)

记录锁(Record Locks)

间隙锁(Gap Locks)

next-key锁

插入意向锁(Insert Intention Locks)

数据库的乐观锁和悲观锁是什么?怎么实现的?

SQL优化

如何定位及优化SQL语句的性能问题?创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?

大表数据查询,怎么优化?

超大分页查询怎么处理?

统计过慢查询吗?对慢查询都怎么优化过?

主键使用自增ID还是UUID?

数据库基本知识

谈谈数据库的三大范式

什么是SQL注入?怎么防止SQL注入


存储引擎

说一说mysql有哪些存储引擎及它们之间有什么区别?

  • Innodb引擎:Innodb引擎提供了对数据库ACID事务的支持,并且还提供了行级锁和外键的约束,采用聚簇索引,同时支持数据库崩溃后的自动恢复。它的设计的目标就是成为能处理大数据容量的数据库系统。
  • MyISAM引擎(原本Mysql的默认引擎):不提供事务的支持,也不支持行级锁和外键,采用非聚簇索引,不支持崩溃后的安全恢复。
  • MEMORY引擎:所有的数据都在内存中,数据的处理速度快,但是安全性不高。

索引

谈一下索引?

索引在数据库中是以文件的形式存在的,通常采用B+树的形式来组织内容,其中叶子结点存储了表中所有数据的引用指针。通过索引能够快速的找到目标叶结点,从而确定要查询的数据。

索引有哪些优缺点?

优点:

  • 能加快查询的效率。每次查询都是B+树从根到叶的一条路径。

缺点:

  • 索引是以文件形式存在的,需要占用物理空间;同时对表中数据进行修改后,索引也要动态维护,耗费时间和资源。

索引的使用场景?

where查询

当查询的列是索引列时,可以直接从索引表定位到具体列,效率很高;而不是索引列时需要遍历整张表,一行行数据的去比较,很耗时。当数据量大的时候效率差距很明显。

order by排序

当使用where+order by的组合时,情况如下:

  1. where和order by字段都建立索引,查询走索引且没有filesort。
  2. where字段建立索引,orderby没索引,查询走where列索引,但是会发生filesort。
  3. where字段没索引,orderby字段有索引,查询不使用索引,发生filesort。
  4. where和orderby字段都没索引,查询不使用索引,发生filesort。

Mysql里的order by与索引 - 风行天下12 - 博客园

join关联查询

对join on中设计的字段建立索引能提高效率。

覆盖索引

当索引覆盖所有的查询字段(包括select后面的,where后面的)时,就能直接从索引表中获取查询数据,不用回表(回磁盘),从而提高效率。

B树和B+树的区别?

B树

  • 每个节点都包含键、值和指向子节点的指针。
  • 叶子结点没有有序链接起来。
  • 查询和删除在全部节点进行。

优点:B树每个节点存储键值,因此可以将频繁访问的数据放在靠近根节点的位置,这样能大大提升数据重复访问的效率。B树主要运用于文见

B+树

  • 非叶节点仅包含键和指向子节点的指针,叶结点包含键、值,由所有节点组成。
  • 叶结点按键大小有序链接起来,方便去做范围查询、排序、遍历等操作。
  • B+树中查询和删除仅在叶结点进行。

优点:B+树非叶节点只存储键,不存储值,因此能在内存也中存放更多的键,方便查询定位。同时,由于所有键值都有序的链接在叶结点上,能方便地进行遍历、范围查询和排序操作。

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

  • B树只适合随机检索,而B+树由于叶结点按键有序排列,既支持随机检索,也支持顺序检索。
  • B+树查询效率更加稳定。因为每次查询都是从根节点到叶结点的过程,而B树靠近根节点的节点查询效率比远一点的节点高。
  • B+树的遍历、排序和范围查询都可以基于有序的叶子链表高效完成,而B树不可以。

索引的数据结构?

索引的数据结构和具体存储引擎有关,MySql中使用较多的索引有哈希索引、B+树索引等,现在最常见的InnoDB存储引擎的默认索引实现是B+树。

1. B+树索引

B+树索引就是把关键字换成了索引列数据,叶结点的指针指向表中索引对应的行数据。

2. hash索引

其实就是把索引值转换成hash值映射到hash表中,对于设置了不唯一主键的表可能会产生hash冲突,此时采用链表法来处理冲突,当按索引查询时也会遍历映射位置的hash链表来找到具体的匹配项,从而获得记录指针。

为什么不用hash索引?

  • hash索引中的数据不是有序存储的,只能做等值查询,不能用来做范围查询或排序。
  • 数据量大时会产生大量的hash冲突,导致效率变低。

B-Tree索引的限制?

假设有索引(last_name, first_name, birthday),last_name是姓,first_name是名。

  • 如果不是按照索引的最左列开始查找,则无法使用索引。比如上面的索引不用能被用来查找名字为Bill的人,也无法查找某个特定生日的人,因为这两列都不是最左列数据。
  • 即使按照最左列查找,但是中间跳过索引中的列,也不能使用索引。比如查找名字为Bill和某个特定日期出身的人的信息,就无法使用索引,因为中间跳过了first_name这个索引列。
  • 如果既按照最左列的原则查找,也没有跳过索引列,但是某个索引列使用了范围查询,可以使用索引,但是这个索引列后面的索引列都不会被用到。比如有“where last_name = 'Smith' and first_name like 'J%' and birthday = '1996-09-15'”,birthday这个索引列就不会被用到,只能使用索引的前两列。

注意:并不是where后面的条件字段必须跟索引列的顺序一样才能使用索引,比如where first_name = 'Tom' and last_name = 'Jerry'也能使用上面索引的前两列查询,“= 和 in”的查询是可以乱序的,而范围查询则不可以。

索引设计的原则?

  • 基数(列中不重复的索引值)较小和更新频繁的列不适合建立索引。如“学号、姓名、性别”这三个列中,性别不适合做索引,因为性别就2种,基数太小。
  • 避免对长字符串列进行索引,可以索引列的部分前缀。
  • 少建单列索引,多建联合索引(如索引a扩展成(a,b)),提高索引的复用性,因为索引会占用磁盘空间,同时修改数据时的动态维护也是一件麻烦的事。
  • 同时注意联合索引中列的顺序,能过滤较多数据的列放在前面。经常范围查询的列放在后面。

百万级别或以上的数据如何删除?

因为数据库删除数据的数量和创建的索引数量是成正比的,所以我们可以先删除索引,然后删除数据。

猜想:可能如果先删除数据的话,mysql检测到数据修改后会去维护索引表,从而多做无用功,浪费系统资源。

Mysql中索引有哪几种?

  • 聚簇索引:每个表都有的索引,以主键列作为索引。
  • 二级索引:除聚簇索引外的所有索引都称作二级索引。如:单列[唯一]索引、组合索引。

最常见的二级索引有有很多种,可以一列建立索引,也可以多列建立索引,可以建立唯一索引(索引列的取值唯一),可以建立非空索引(索引列的取值不为null),也可以建立唯一非空索引,也可以建立前缀索引,也可以建立全文索引,反正他们都叫“二级索引”

--创建普通索引
CREATE INDEX index_name ON table_name(col_name);
--创建唯一索引
CREATE UNIQUE INDEX index_name ON table_name(col_name);
--创建普通组合索引
CREATE INDEX index_name ON table_name(col_name_1,col_name_2);
--创建唯一组合索引
CREATE UNIQUE INDEX index_name ON table_name(col_name_1,col_name_2);
--建立全文索引
ALTER TABLE article ADD FULLTEXT INDEX fulltext_article (title, content)

聚簇索引和非聚簇索引(二级索引)的区别和联系?

概念

聚簇索引是B+树索引和行数据的结合,它的叶节点上存储了表中的数据行而不再是数据指针。在InnoDB中,默认会选择主键作为聚簇索引列,没有主键则会选择一个非空列代替,非空列都没有的话会隐式定义一个主键来作为聚簇索引;MyISAM没有聚簇索引。

聚簇索引之外的索引都被称为二级索引。就是普通的B+树索引,非叶节点存储索引列和指向子树的指针,叶结点存储了所有索引列和对应的数据指针,并有序地形成一个链表。使用非聚簇索引时,MyISAM存储引擎的叶结点存储的是行指针,InnoDB的叶结点存储的是主键(不是指向行在外存中的物理地址)

All indexes other than the clustered index are known as secondary indexes.A secondary index can be used to satisfy queries that only require values from the indexed columns. For more
complex queries, it can be used to identify the relevant rows in the table, which are then retrieved through lookups
using the clustered index.

二级索引如何和聚簇索引交互?

在InnoDB中,当查询使用的是二级索引而不是聚簇索引时,就会先在二级索引表中搜索,找到匹配的主键,然后根据主键在聚簇索引表中找到对应的数据行。如果查询仅仅涉及到主键,则不需要查询二级索引表。

In InnoDB, each record in a
secondary index contains the primary key columns for the row, as well as the columns specified for the
secondary index. InnoDB uses this primary key value to search for the row in the clustered index.

全文索引(FULL-TEXT INDEX)

mysql5.7 中,InnoDB支持全文索引。

全文索引只能包含类型为(CHAR,VARCHAR,TEXT)的列,使用全文索引能加速包含索引列的查询,查询过程中会忽略所有的停用词(stopwords,可以使用 SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD; 来查询)。全文索引可以使用CREATE TABLE..、ALTER TABLE或CREATE INDEX来创建,使用的语法为:MATCH()...AGAINST。它能够利用“分词技术“等多种算法智能分析出文本文字中关键字词的频率及重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。

--创建
CREATE TABLE article (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,title VARCHAR(200),content TEXT,FULLTEXT (title, content) --在title和content列上创建全文索引
);--查询
SELECT * FROM article WHERE MATCH(title, content) AGAINST('查询字符串')

前缀索引

语法:index(field(n)),使用字段的前n个字符建立索引,最常见于长字符串索引列(如以UUID作为主键的表)。难度是长度n的选取,要在索引命中率和存储空间上作一个选择。短了命中率会降低,因为同一个前缀会有很多行匹配;长了命中率会提高,但是存储空间会变大。

长度选取方法:计算索引列中前n个字符相同的记录的数量然后分组,就得出了每个前缀出现的次数,然后不断地调整n,使得整个每个前缀出现次数的平均值最小。P154.

什么是左前缀(匹配)原则?

  • mysql会按照索引列的定义顺序来匹配,直到遇到范围查询(>、<、between、like【like查询以通配符开头或like查询的列不是前缀索引时,不能使用索引,反之可以】等,in不是范围查询)。比如定义了索引(a,b,c,d),在select * from table1 where a = 1 and b = 2 and c > 3 and d = 4 中,d是用不到索引的,这意味着要遍历根据a,b,c索引查出来的数据记录,一条条判断d=4是否成立。但如果定义成(a,b,d,c)或(b,d,a,c)这种形式,即把c放到索引列的最后,那么就能匹配所有索引列了。
  • =和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。

索引覆盖

如果一个索引包含所有需要查询的字段和where后条件判断的字段,我们称之为“索引覆盖”。因为要查询的数据可以直接从索引表中获得,所以不用回表取数据。

什么是联合索引?为什么要注意联合索引中列的顺序?

联合索引就是使用多个列构成一个索引。

联合索引中列的顺序至关重要,因为当使用索引查询时,会按从左到右的顺序进行过滤。如过有索引(school,age,name),和下面sql,这个查询的效率是很低的:

select otherInfo from user where name = 'tom' and age > 18 and school = 'qinghua'

因为查询会先判断school = 'qinghua'这个条件,依据该条件查出来的结果远比name=‘tom’多的多,所以第一个要注意的就是把能过滤尽可能多数据的列放在联合索引的前面。

其次MySql中对于范围条件(<,>,between)的查询,无法再使用范围列后面的其它索引列。即上面的sql不能使用name进行索引查询了。所以第二个要注意的是要把范围查询列放到联合索引的最后。

事务

什么是事务?事务的四大特性介绍一下

事务是一组原子操作,事务中的操作要么都执行,要么都不执行。

事务四大特性(ACID):

  • 持久性:事务一旦被提交,对数据库的修改是永久性的。
  • 原子性:事务中的操作要么都执行,要么都不执行。
  • 隔离性:当并发访问数据库时,事务之间不会相互干扰。即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
  • 一致性:事务执行前后数据库必须处于一致性状态。如A和B共有5000元,不管在事务中怎么转账,A和B的钱的总和还是5000不变。

SQL执行的过程?

见下面(事务实现的原理)。

谈谈事务的实现原理?(redo log+undo log+锁、MVCC)

参考自:https://www.cnblogs.com/wyc1994666/p/11367051.html。

实现事务,就是要实现事务的四个特性(ACID),假设原始数据如下:

  • 持久性:通过redo log实现。在事务执行过程中,会将每次更新之后和之前的值存在redo log buffer和undo log buffer中。当发起提交事务的请求后,mysql会将redo log buffer和undo log buffer中的数据刷到磁盘上的redo log(顺序IO,性能消耗小)和undo log中,刷完之后事务提交成功事务中的更新之后的结果先会存放在buffer pool(随机IO,性能消耗大)中,InnoDB会开启一个异步线程去将其中的数据同步到磁盘上的数据页中,这个同步不是实时的。如果在同步回磁盘之前宕机,那么数据会丢失,这就违背了持久性,可以在之后通过redo log来恢复,这就保证了持久性。

  • 原子性:通过undo log来实现。undo log记录数据在事务之前的状态,主要用于数据回滚和MVCC,比如事务在没有提交的情况下数据库发生错误,则可以通过undo log恢复到事务之前的状态,即要么执行,要么不执行。
  • 隔离性:通过各种锁和MVCC来保证各个事务之间的操作互不干扰。
  • 一致性:通过原子性、持久性、隔离性来实现。

什么是脏读、幻读、不可重复读、丢失修改?

回滚是回滚事务中未提交的修改。在Mysql中,事务未提交的修改对其它事务是透明的,因此如果有多个事务并发访问数据库,就会出现数据的不一致性,主要包括:脏读、幻读(不可重复度)和丢失修改。

下面A和B是同一个事务,所有操作都是在同一个事务中。

  • 脏读:事务A读取了事务B修改但没提交的数据,之后事务B被回滚,此时事务A读到的就是脏数据。
  • 不可重复读:事务A读取了某一数据后,事务B对该数据进行了修改操作,之后事务A再查询该数据时发现与上一次读取的内容不一样。
  • 幻读:事务A读取了某一范围的数据后,事务B在该范围内进行了插入、删除操作,之后事务A再查询该范围数据时会发现与之前数量不一样,就像出现了幻觉一样。
  • 丢失修改:事务A和B同时读取了某一数据并进行修改,但事务B的修改破坏了事务A的修改。如:有一个全局变量a = 10,事务A读取并+1,结果为11;事务B同样读取并+1,结果也为11。提交之后a就是11,等于让事务A的修改作废了。

一致性读(consistent read)

一致性读就是读取数据库某个时间点的快照数据作为结果的读操作。快照是数据库在某一时间点的数据状态。在REPEATABLE-READ隔离级别中,在同一个事务中,快照是select操作第一次被执行时产生的,后面的select读取的都是第一次select产生的快照信息,所以即使其它事务修改了数据,读取的结果不会改变,这就实现了可重复读;而在READ-COMMITTED隔离级别中,事务中的每次select都会产生一个新的快照,所以避免不了可重复读。

MySql中的四个隔离级别?

从上往下隔离级别由低到高:

  • READ-UNCOMMITTED(读取未提交):允许读取事务尚未提交的数据。会导致脏读、不可重复读、幻读。
  • READ-COMMITTED(读取已提交):只允许允许读取事务已经提交的数据。不会导致脏读,会导致不可重复读、幻读。
  • REPEATABLE-READ(可重复读):同一事务多次执行select的结果一样,即读到的是相同的数据,通过快照读(一致性读)和行锁(执行select ... for update这类的语句使用next-key锁)来实现可重复读。可以防止脏读、不可重复读,通过快照读和间隙锁(执行select ... for update这类的语句使用next-key锁)来防止幻读。
  • SERIALIZABLE(可串行化):跟REPEATABLE-READ类似,但是如果事务的的自动提交没有开启(一般都不会开启),InnoDB会隐式地把每一个普通的select(plain select)变成select...lock in share mode((在RR隔离级别下,select...for update和select...lock in share mode等这些查询会默认加间隙锁),即select的所有rows被加上了共享锁,其它事务只能读,不能写。解决脏读、不可重复读,不可重复读。

什么是MVCC(多版本并发控制)?

MVCC实现了快照读,保证了一个事务的查询结果不会受到其它事务操作的影响,解决了事务在普通查询下的不可重复读和幻读的问题。

InnoDB中每个事务都有一个版本号。InnoDB为每行记录添加两个隐藏列,分别保存创建它的事务版本和删除它的事务版本,并且规定了CRUD的具体操作如下:

  • 查询:一个事务只能查到 行的创建版本号小于等于当前事务版本、行的删除版本号大于当前事务版本 的行数据。保证当事务创建时,数据已经存在。
  • 插入:将当前事务版本设置为插入行的创建版本号。
  • 删除:将当前事务版本设置为删除行的删除版本号。
  • 修改:设置修改行的删除版本为当前事务版本,然后新插入这条修改后的数据并设置创建版本为当前事务版本。

在上面的规则下,事务每次在进行普通select时,相当于生成了一张数据快照,以后每次查询都是从快照中读取数据,这样就不会受到其它事务的干扰。

谈谈快照读和当前读?

快照读

定义:快照读就是生成一张数据在某个时间点的快照,使相关查询可以直接从快照中读取数据。

实现:快照读的主要实现方式就是MVCC,通过为每行记录添加两个隐藏列,用来存储创建事务版本和删除事务版本,制定相应的CRUD规则来实现快照读。

触发操作:当进行单纯的select操作时触发快照读(不包括上述 select ... lock in share mode, select ... for update)。

优缺点:能够防止不可重复读和幻读,但是读到的可能是过期的数据。

当前读

定义:每次读取到的是最新的数据。

实现:next-key锁(行锁和间隙锁的组合)。

触发操作:select...lock in share mode (加读锁)
                    select...for update(加写锁)
                    update , delete , insert(都是写锁)

优缺点:行锁能够防止数据被其它事务修改(不可重复度)和删除(幻读),间隙锁能够防止其它事务往查询的区间内插入新的数据(幻读)。

MySql如何防止幻读?

简单的select查询是快照读,在RR隔离级别下通过MVCC能搞防止幻读;进行当前读的操作时,在RR级别下是通过next-key锁(行锁+间隙锁)来防止幻读。即使如此,还是有一种情况避免不了,那就是在快照读时读到了过期的数据,然后变成当前读之后就读到了其它事务新插入的数据。

MySql中的锁

详情见阿里技术:一个线上SQL死锁异常分析:深入了解事务和锁

Mysql中有哪几种锁?

以下内容90%来自mysql 5.7官方文档,有兴趣的可以直接看原文。

共享锁(S)和排它锁(X)

都属于行锁,当一行数据被添加共享锁时,其它事务只能读取不能修改;当一行数据被添加排它锁时,其它事务的读取和修改操作都被禁止。

意向锁(Intension Locks)

分为意向共享锁(IS)和意向排它锁(IX)。意向锁协议:1、一个事务在获取S锁之前必须先或许IS锁;2、一个事务在获取X锁之前 必须先获取IX锁。一个事务获得IS锁表示这个事务准备为一行记录添加S锁,一个事务获得IX锁表示这个事务准备为一行记录添加X锁,意向锁存在的目的就是为了说明有事务正在或将要锁定一行记录,那这到底有什么意义呢?

在MySql中,可以为一张表添加S/X锁,也可以为一张表中的某几行添加S/锁,如下。显然,事务A获取了tab表的X锁,事务B就不能获取其它任意锁;同理,事务A获取了id=1的X锁,事务B就不能获取tab表的X/S锁,其它情况就不一一介绍了。在没有意向锁的情况下,事务A想要获取tab表的X锁,则必须遍历tab中所有的记录,看看有没有加X/S锁的情况,有就不能获取表的X锁,这样就很麻烦。但是,有了意向锁就不一样了,上面说了,意向锁存在的目的就是为了说明有事务正在或将要锁定一行记录,我不管这里的事务有多少个,不管要锁定的行记录有多少条,意向锁只说明“有事务锁定了某行”即可,可以把IS锁和IX锁看成两个字段boolean flagIS和boolean flagIX。这时如果事务A要获取tab表的X锁,只要判断(flagIS || flagIX)是否为true,是就不能获取表锁,否就直接获取;如果事务A想要获取tab表的S锁,就判断(flagIX)是否为true即可,这样就省去了遍历整张表的麻烦。

lock tables tab write                          # 为表tab添加X锁
lock tables tab read                           # 为表tab添加S锁
select * from tab where id = 1                 # 为表tab中id=1的记录添加S锁
update tab set name = 'zkw' where id = 1       # 为表tab中id=1的记录添加X锁

意向锁仅仅会阻塞获取整张表的锁的请求,不会阻塞任何其他请求,IS和IX锁之间是兼容的,事务A获取了IX锁,事务B依然可以获取IS锁和IX锁。

记录锁(Record Locks)

记录锁锁一个具体的索引记录(index record),就是对一行数据上的索引进行加锁。比如下面SQL执行后,Mysql会阻止其它事务插入、修改、删除t.c1>10的记录,不管记录是否存在。当某个表没有定义索引,比如t.c1不是索引,InnoDB会创建一个隐藏的聚簇索引,然后用这个索引来作为记录锁锁定的对象。

SELECT c1 FROM t WHERE c1 > 10 FOR UPDATE;

间隙锁(Gap Locks)

根据唯一索引进行等只查询,在命中的情况下只会对命中的行加排它锁,不会加间隙锁;其它索引查询会有间隙锁。

  • 锁某个间隙(gap),这个间隙可能是两个索引记录之间的范围(如a~b),也可能是a之前,也可能是b之后。间隙可能跨越(span)单个索引值、多个索引值,甚至可以是空(empty)。
  • 间隙锁的目的是防止因其它事务不合时宜的插入导致的幻读。
  • 当使用唯一索引(唯一索引不允许具有索引值相同的行,如主键)进行等值查询时不会出现间隙锁,如其它情况则会出现。如下面sql,id为主键,则执行select语句后仅仅使用记录锁对id=100的行的索引加锁,不会锁住前面的间隙(the preceding gap),如id<100的间隙。如果id不是索引或者是一个非唯一索引,那么这条语句就会锁住前面的间隙。
SELECT * FROM child WHERE id = 100 for update;
  • 间隙锁出现在RR隔离级别中,RU和RC中没有间隙锁。

next-key锁

根据非唯一索引等值查询命中时,会对命中的行加排它锁,也会对记录前后区间加间隙锁,这就是next-key锁。

当执行select...lock in share mode,select...for update,update , delete , insert操作时,就会被应用到目标数据行上(被查询、插入、修改、删除的行)。

是记录锁和间隙锁(锁某个索引记录之前的间隙,before the index record)的组合形式,在RR级别下被运用。当在查询和浏览索引时,会为每一个遇到的索引添加记录锁,假设执行下面的sql,显然InnoDB要扫描id为10,11,13,20的row,因此会为这些row添加记录锁,除此之外,也会为加锁记录前的间隙加锁。整个SQL执行后,最终的锁定范围如下,锁定范围内不能进行增删改操作,避免出现幻读。

  • 会锁定(上一个存在索引,当前添加记录锁的索引]。
  • 对于遍历索引中的最后一个记录,会锁定它后面的间隙。
# tab表中rows的age包括:4,10,11,13,20
select * from tab where age = 10 for update;    # 加锁范围:(4,10]
select * from tab where age > 13 for update;    # 枷锁范围:(13,20]U(20,positive infinity)# 整个next-key锁可能加锁的范围
(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)

插入意向锁(Insert Intention Locks)

插入意向锁就是一种类型间隙锁,在执行insert操作时加锁到insert索引的上下索引区间上,如数据库中有4,7两条记录,你插入5或6,就会给(4,7)这个区间加插入意向锁。

它的作用和上面的意向锁一样,也仅仅是为了说明在某个区间内有事务准备或正在执行insert操作,这样一来,那些想要给这个区间加间隙锁或next-key锁(就是锁住这个区间,不让其他事务读或写这个索引区间的数据)的事务直接判断这个区间有没有插入意向锁,有就等待,没有就锁住。

多个事务可以同时获取同一个区间的插入意向锁,只要他们插入记录的索引值不相同,那就不会发生阻塞情况,如上面例子,事务A和事务B分别插入5、6,都可以正常插入。

下面因子官方案例,经过自己测试,在创建child表和插入90、102两条数据后,不管是事务A或事务B谁先执行,后执行的事务总是会阻塞。道理很简单,我查这个区间时,你不能往这个区间里面插入数据;我往这个区间插入数据时,你不能查这个区间。

数据库的乐观锁和悲观锁是什么?怎么实现的?

  • 乐观锁:假设事务之间不会产生并发问题,进行数据操作时才会判断数据是否被修改,这个判断是通过版本号控制(事务提交时检测版本号是否被修改)和CAS操作来实现的。
  • 悲观锁:假设事务之间会产生并发问题,在操作数据之前会对数据加锁(行锁,间隙锁等)。主要通过数据库的锁机制来实现的。

SQL优化

如何定位及优化SQL语句的性能问题?创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?

判断一条sql的性能就看它有没有合理地使用索引。使用explain命令能查看sql的执行计划,其中包含了sql是否使用索引、使用什么索引及索引的相关信息等。通过type列的值可以知道查询的方式,是全表扫描(ALL)、还是遍历索引或范围索引查找等。extra列的值可以判断是否使用了覆盖索引(Using index)。

大表数据查询,怎么优化?

  • 首先从代价最低的方法着手,对sql语句进行优化。通过explain命令查看sql的具体信息,定位慢查询,然后优化索引的使用。
  • 如果sql优化对查询效率提升不大,再考虑表结构的设计是否合理,讨论通过重新设计表是否能让查询使用更优的索引策略。当然,这种情况不常见,如果真要修改会付出比较大的代价。
  • 之后可以采取横向和纵向的分表。横向分表就是创建多张相同结构的表,将数据按照某种规则平均放在这些表中;纵向分表就是将一个业务表按列拆分成不同的表,分别存储不同类型的数据。mysql 分表-横向,纵向 - 星朝 - 博客园
  • 然后也可以使用缓存应用,比如redis、memcached。当然这对服务器内存有一定要求。
  • 也可以使用读写分离,设置多台读服务器和少数写服务器。这需要一定的硬件资源。

超大分页查询怎么处理?

mysql中的分页查询不会直接跳到offset行,而是读取offset+N行之后抛弃前面的offset行,这样的话当offset很大的时候效率就非常低。

下面是错误sql查询,会现在表中读取1000010行数据,然后舍弃前面的1000000行数据,效率很低。

select * from table where age > 20 limit 1000000,10

可以进行子查询优化,先使用覆盖查询查出目标行的主键,然后直接通过主键查出所有目标行。因为覆盖索引所需的数据都在索引表中,不用回表,所以效率非常高,同时舍弃的也只是offset个主键,不是整行的数据。之后通过id进行索引等值查询也是一个高效动作。

select * from table where id in (select id from table where age > 20 limit 1000000,10)

统计过慢查询吗?对慢查询都怎么优化过?

慢查询统计

可以使用show variables like ‘slow_query_log’查看是否开启,如果状态值为OFF,可以使用set GLOBAL slow_query_log = on来开启,它会在datadir下产生一个xxx-slow.log的文件。

慢查询优化

  • 首先检查查询有没有加载多余的数据,可能是查询了多余的行然后抛弃掉,也可能是查询了不需要的列,根据具体问题进行优化。
  • 使用explain命令分析sql的执行计划,查看索引的使用情况,通过修改sql或索引来提高索引的命中率。
  • 如果对sql的优化不能解决查询慢的问题,可以考虑数据量是否过大,是的话可以进行横向或纵向的分表,或采用缓存和读写分离等策略。

主键使用自增ID还是UUID?

推荐使用自增ID。

  • 自增id比UUID长度短,索引表所占的磁盘空间也少很多。
  • 使用自增ID时,索引树的构造和维护要比使用UUID简单的多,效率更高。
  • 当按索引进行查询时,自增ID的比较比UUID简单,效率更高。

数据库基本知识

谈谈数据库的三大范式

首先明确:完全依赖、部分依赖、传递依赖(间接依赖)的概念。以学生表为例

  • 完全依赖:比如学生的学号(主键)能得出(唯一表示)学生的姓名、性别、班级、宿舍号等信息,就说姓名、性别、班级完全依赖于学号。
  • 部分依赖:学生的成绩不仅仅是由学号决定,而且由相关的课程号决定,即成绩完全依赖于(学号,课程号),部分依赖于学号或课程号。
  • 传递依赖:比如宿舍地址完全依赖于宿舍号,而宿舍号又完全依赖学号,所以宿舍地址传递依赖(间接依赖)于学号。

完全依赖与部分依赖是相对的,两个字段间,要么不依赖,要么是完全依赖,要么是部分依赖。传递依赖与他们不是一类,有完全传递依赖和部分传递依赖。

  • 第一范式:数据库表中所有字段值都是不可分解的原子值。
  • 第二范式:表中每列必须完全依赖于主键(不能是部分依赖,可以是完全传递依赖)。比如不能把与学生信息无关的列放到学生表中,可以把宿舍地址放到学生表中。
  • 第三范式:表中每列既不能部分依赖,也不能传递依赖于主键。比如你可以在学生表中加“宿舍号”(外键)这个列,但不能直接加“宿舍地址”这一列,因为学号——>宿舍号——>宿舍地址。

什么是SQL注入?怎么防止SQL注入?

【阿里巴巴/腾旭】mysql面试题汇总相关推荐

  1. 初级mysql面试题汇总

    本人学习了解了一些mysql的知识,也曾面试过mysql的数据库管理员,现与大家分享一些mysql初级的面试题. Mysql的存储引擎,myisam与innodb的区别. 答: 1.myisam是非事 ...

  2. MySQL 面试题汇总

    1.说一下 MySQL 执行一条查询语句的内部执行过程? 答:MySQL 执行一条查询的流程如下: 客户端先通过连接器连接到 MySQL 服务器: 连接器权限验证通过之后,先查询是否有查询缓存,如果有 ...

  3. 2万字高频MySQL面试题总结(含答案),金九银十成为offer收割机!【建议收藏】

    大家好,我是yes. 这篇是MySQL 面试题汇总,所有的答案都是我原创的,来来回回差不多整理个一个月左右,如果有什么问题,还请留言区指正! 话不多说,请接招! 你们公司数据库有备份的吧? 我:有的, ...

  4. 【Mysql笔试】-常见笔试题汇总

    Mysql常见笔试题汇总 基础知识 排序的规则? 函数的分类?经常使用的函数? 分组查询注意条件? limit使用方法? 创建表时有什么约束条件? mysql常见数据类型? 增加删除修改表结构 常见约 ...

  5. 阿里巴巴历年经典面试题汇总:Java岗

    这个系列计划收集几百份朋友和读者的面经,作者合集方便查看,各位有面经屯着可以联系我哦 本系列历史文章: 学姐百度实习面经 学姐,来挑战字节最牛部门 最强阿里巴巴历年经典面试题汇总:C++研发岗 关于我 ...

  6. 超经典,阿里巴巴历年高频面试题汇总:前端岗

    这个系列计划收集几百份朋友和读者的面经,作者合集方便查看,各位有面经屯着可以联系我哦 本系列历史文章: 阿里巴巴历年经典面试题汇总:Java岗 学姐百度实习面经 学姐,来挑战字节最牛部门 最强阿里巴巴 ...

  7. 阿里巴巴历年在线笔试题汇总

    阿里巴巴在线笔试题汇总 2013阿里巴巴前端在线笔试题 1.现有代码如下: 2.如果你现在使用的是 Google Chrome 或 Apple Safari,如何让 input 元素在默认情况下显示 ...

  8. 阿里巴巴面试题汇总(java方向) 带答案

    阿里巴巴面试题汇总 1.一.String,StringBuffer, StringBuilder 的区别是什么?String为什么是不可变的? 1.String是字符串常量,StringBuffer和 ...

  9. 2015年阿里巴巴校招研发工程师在线笔试题汇总

    在线笔试题汇总 卷一: 1.下面的函数中哪个是系统调用而不是库函数______?  printf  scanf  fgetc  read  print_s  scan_s 2.某足球队有四名外援,分别 ...

  10. 网易校园招聘历年经典面试题汇总:C++研发岗

    这个系列计划收集几百份朋友和读者的面经,作者合集方便查看,各位有面经屯着可以联系我哦 这个系列离结束差的还特别多,会更新涵盖所有一线大厂的所有岗位,也可以关注一下. 腾讯校园招聘历年经典面试题汇总:前 ...

最新文章

  1. 如何保持空域与频域滤波结果的一致性
  2. Spring MVC报错:The request sent by the client was syntactically incorrect ()
  3. VMware虚拟机网络模式详解 NAT模式
  4. S/4HANA的生产订单,哪个字段可以用来做生产完成的标志位
  5. 不属于python标准库的是_python标准库和扩展库
  6. sqlalchemy外键和relationship查询
  7. Java中父类强制转换为子类的可能
  8. cocos2dx的runAction: 反复运行,多个动作连接运行,多个动作同一时候运行的实现
  9. Spring+Netty4实现的简单通信框架
  10. SQL 查询所有表名、字段名、类型、长度、存储过程、视图
  11. [文摘20080908]哈佛大学成功25句
  12. gear操作系统 基于web的linux开放平台,支持Linux操作系统 开源飞机模拟器FlightGear...
  13. 板凳——————————————————c++(104)
  14. 最长单调递增子序列问题 设计一个O(n2)复杂度的算法,找出由n个数组成的序列的最长单调递增子序列
  15. xp系统如何开启ftp服务器,xp系统怎么开ftp服务器
  16. 我喜欢用计算机300,我喜欢的人_作文300字_小学四年级作文_第一范文网
  17. 11 wifi6速率_使用高端的WIFI6路由器是什么体验?Orbi RBK752
  18. python snmp-cmds get示例
  19. 小姜的毕设_Software
  20. 文字图片白底黑字_白底黑字简短文字图片 白底黑字纯简短文字

热门文章

  1. Redis HyperLogLog 是什么?这些场景使用它,让我枪出如龙,一笑破苍穹
  2. oracle几何体数据类型,4.1 Oracle中空间几何体的类型
  3. 小学生的游戏 FZU - 1575
  4. 秒变“女装大佬”!Snapchat推出性别转换滤镜,离线实时渲染(附测评)
  5. 【微服务】Nacos 注册中心的设计原理
  6. [灯哥开源—四足机器人]程序算法讲解与STM32移植——运行框架(两个主线程)
  7. java游戏英雄时代攻略_军团战棋英雄时代战役攻略 战役全关卡通关攻略
  8. php excel速度慢,window_win10双击打开excel太慢了的三种解决办法,win10双击打开excel文件慢该怎么 - phpStudy...
  9. 南京大学计算机视觉博士生导师,孙正兴——著名计算机专家孙正兴——南京大学教授...
  10. 基于ZYNQ的VGA驱动