MySQL性能调优(十二):MySQL8常见面试题(二)

文章目录

  • MySQL性能调优
    • 数据库设计优化
    • 查询优化
    • 配置参数调整
    • 硬件优化
    • 主键和唯一键有什么区别?
    • 说说对SQL语句优化有哪些方法?(选择几条)
    • 如何提高insert的性能?
    • 什么是覆盖索引?什么是回表查询?
    • 什么是三星索引?
    • 大表关联查询优化
    • \[SELECT \*] 和\[SELECT 全部字段]有何优缺点?
    • 请概述下什么是MySQL的分区表
    • 说几条MySQL对SQL的执行做的优化手段
    • InnoDB引擎的三大特性是什么?
    • redolog和binlog的区别是什么?
    • MySQL崩溃后的恢复为什么不用binlog?
    • MySQL如何实现事务的ACID?
    • InnoDB事务是如何通过日志来实现的?
    • 什么是当前读和快照读?
    • 什么是MVCC?
    • MVCC的底层实现原理是什么?
    • 什么是锁?MySQL 中提供了几类锁?
    • 什么是全局锁、共享锁、排它锁?
    • MySQL中的表锁有哪些?
    • InnoDB引擎的行锁是怎么实现的?
    • 谈一下MySQL中的死锁
    • 简述下MySQL8中的新增特性有哪些

在这里插入图片描述
个人主页:道友老李
欢迎加入社区:道友老李的学习社区

MySQL性能调优

MySQL 性能调优是一个复杂且多维度的过程,下面从数据库设计、查询优化、配置参数调整、硬件优化几个方面为你介绍相关的调优方法。

数据库设计优化

  • 合理设计表结构:确保表结构遵循数据库设计范式,减少数据冗余,同时要根据实际业务需求灵活调整,避免过度范式化导致的查询复杂度过高。
  • 选择合适的数据类型:使用合适的数据类型可以减少存储空间,提高查询性能。例如,对于固定长度的字符串使用CHAR,对于可变长度的字符串使用VARCHAR;对于整数类型,根据取值范围选择合适的类型,如TINYINTSMALLINT等。
  • 建立适当的索引:索引可以加快数据的查找速度,但过多的索引会增加写操作的开销,因此需要根据查询需求建立适当的索引。例如,对于经常用于WHERE子句、JOIN条件和ORDER BY子句的列,可以考虑创建索引。

查询优化

  • 避免全表扫描:尽量使用索引来避免全表扫描,例如在WHERE子句中使用索引列进行过滤。
  • 优化子查询:子查询可能会导致性能问题,可以考虑使用JOIN来替代子查询。
  • 减少不必要的列:在查询时只选择需要的列,避免使用SELECT *

配置参数调整

  • 调整内存分配:根据服务器的硬件资源和业务需求,调整innodb_buffer_pool_sizekey_buffer_size等参数,以提高缓存命中率。
  • 调整日志参数:根据业务需求调整log_bininnodb_log_file_size等参数,以平衡数据安全性和性能。

硬件优化

  • 使用高速存储设备:如 SSD 可以显著提高磁盘 I/O 性能。
  • 增加内存:足够的内存可以减少磁盘 I/O,提高查询性能。

主键和唯一键有什么区别?

主键不能重复,不能为空,唯一键不能重复,可以为空。

建立主键的目的是让外键来引用。

一个表最多只有一个主键,但可以有很多唯一键

说说对SQL语句优化有哪些方法?(选择几条)

(1)Where子句中:where表之间的连接必须写在其他Where条件之前,那些可以过滤掉最大数量记录的条件必须写在Where子句的末尾.HAVING最后。

(2)用EXISTS替代IN、用NOT EXISTS替代NOT IN。

(3) 避免在索引列上使用计算

(4)避免在索引列上使用IS NULL和IS NOT NULL

(5)对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

(6)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

(7)应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。

如何提高insert的性能?

答:有如下方法:

a)合并多条 insert 为一条,即: insert into t values(a,b,c), (d,e,f) ,

原因分析:主要原因是多条insert合并后日志量(MySQL的binlog和innodb的事务日志) 减少了,降低日志刷盘的数据量和频率,从而提高效率。通过合并SQL语句,同时也能减少SQL语句解析的次数,减少网络传输的IO。

b)修改参数bulk_insert_buffer_size, 调大批量插入的缓存;

c)设置 innodb_flush_log_at_trx_commit = 0 ,相对于 innodb_flush_log_at_trx_commit = 1 可以十分明显的提升导入速度;

(备注:innodb_flush_log_at_trx_commit
参数对 InnoDB Log 的写入性能有非常关键的影响。该参数可以设置为0,1,2,解释如下:

0:log buffer中的数据将以每秒一次的频率写入到log file中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file 的刷新或者文件系统到磁盘的刷新操作;

1:在每次事务提交的时候将log
buffer 中的数据都会写入到log file,同时也会触发文件系统到磁盘的同步;

2:事务提交会触发log buffer 到log file的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。)

d)手动使用事务

因为mysql默认是autocommit的,这样每插入一条数据,都会进行一次commit;所以,为了减少创建事务的消耗,我们可用手工使用事务,即START TRANSACTION;insert 。。,insert。。 commit;即执行多个insert后再一起提交;一般1000条insert 提交一次。

什么是覆盖索引?什么是回表查询?

InnoDb存储引擎有两大类索引聚集索引和普通(辅助/二级)索引,聚簇索引的叶子节点存储行记录,因此InnoDb必须要有聚簇索引且仅有一个聚簇索引,而普通索引的叶子节点只存储索引值和主键值,所以,通过聚簇索引一次性能获取所有列的数据,普通索引一般不行。

当我们SQL语句的中列无法在普通索引中获得时,就需要主键值到聚簇索引中获取相关的数据,这个过程就被称为回表。

而如果我们使用联合索引,使得SQL所需的所有列数据在这个索引上就能获得时,我们称为发生了索引覆盖或者覆盖索引。

什么是三星索引?

对于一个查询而言,一个三星索引,可能是其最好的索引。

如果查询使用三星索引,一次查询通常只需要进行一次磁盘随机读以及一次窄索引片的扫描,因此其相应时间通常比使用一个普通索引的响应时间少几个数量级。

一个查询相关的索引行是相邻的或者至少相距足够靠近的则获得一星;

如果索引中的数据顺序和查找中的排列顺序一致则获得二星;

如果索引中的列包含了查询中需要的全部列则获得三星。

三星索引在实际的业务中如果无法同时达到,一般我们认为第三颗星最重要,第一和第二颗星重要性差不多,根据业务情况调整这两颗星的优先度。

大表关联查询优化

一个6亿的表a,一个3亿的表b,通过tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录。

1、如果A表TID是自增长,并且是连续的,B表的ID为索引

select * from
a,b where a.tid = b.id and a.tid>500000 limit 200;

2、如果A表的TID不是连续的,那么就需要使用覆盖索引.TID要么是主键,要么是辅助索引,B表ID也需要有索引。

select * from b
, (select tid from a limit 50000,200) a where b.id = a .tid;

[SELECT *] 和[SELECT 全部字段]有何优缺点?

1>.前者要解析数据字典,后者不需要

2>.结果输出顺序,前者与建表列顺序相同,后者按指定字段顺序。

3>.表字段改名,前者不需要修改,后者需要改

4>.后者可以建立索引进行优化,前者无法优化

5>.后者的可读性比前者要高

请概述下什么是MySQL的分区表

表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分。从逻辑上看,只有一张表,但是底层却是由多个物理分区组成。

1、表分区与分表的区别

分表:指的是通过一定规则,将一张表分解成多张不同的表。比如将用户订单记录根据时间成多个表。

分表与分区的区别在于:分区从逻辑上来讲只有一张表,而分表则是将一张表分解成多张表。

2、表分区的好处?

1)存储更多数据。分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备。和单个磁盘或者文件系统相比,可以存储更多数据

2)优化查询。在where语句中包含分区条件时,可以只扫描一个或多个分区表来提高查询效率;涉及sum和count语句时,也可以在多个分区上并行处理,最后汇总结果。

3)分区表更容易维护。例如:想批量删除大量数据可以清除整个分区。

3、分区表的限制因素

一个表最多只能有1024个分区

如果分区字段中有主键或者唯一索引的列,那么多有主键列和唯一索引列都必须包含进来。即:分区字段要么不包含主键或者索引列,要么包含全部主键和索引列。

分区表中无法使用外键约束

MySQL的分区适用于一个表的所有数据和索引,不能只对表数据分区而不对索引分区,也不能只对索引分区而不对表分区,也不能只对表的一部分数据分区。

4、分区表的类型

RANGE分区: 这种模式允许将数据划分不同范围。例如可以将一个表通过年份划分成若干个分区

LIST分区: 这种模式允许系统通过预定义的列表的值来对数据进行分割。按照List中的值分区,与RANGE的区别是,range分区的区间范围值是连续的。

HASH分区 :这中模式允许通过对表的一个或多个列的Hash
Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区。例如可以建立一个对表主键进行分区的表。

KEY分区 :上面Hash模式的一种延伸,这里的Hash
Key是MySQL系统产生的。

Column分区:需要和RANGE和List结合,支持字符串和日期的分区,也支持多列分区。

复合分区/子分区:分区之下还可以再分区。

5、在实际工作中用分区表比较少

1)分区表,分区键设计不太灵活,如果不走分区键,很容易出现全表锁

2)自己分库分表,自己掌控业务场景与访问模式,可控。分区表,研发写了一个sql,都不确定mysql是怎么操作的,不太可控

3)分区表无论怎么分,都是在一台机器上,天然就有性能的上限。

说几条MySQL对SQL的执行做的优化手段

1、对SQL语句的优化,MySQL会对我们的SQL语句做重写,包括条件化简,比如常量传递、除没用的条件等等;还会将一些外连接转换为内连接,然后选择成本最低的方式执行;对IN子查询会进行物化、物化表转连接查询、转换为半连接等方式进行。

2、在SQL语句的执行过程中,MySQL引入了索引条件下推。比如where后面的多个搜索条件都使用到了一个二级索引列,这些搜索条件中虽然出现了索引列,有些却不能使用到索引,像like ‘%…’查询,MySQL为了避免不必要的回表,从二级索引取得的索引记录,先做条件判断,如果条件不满足,则该二级索引记录不会去回表,这样可以大量的减少回表操作的随机IO成本。

3、在回表操作上,因为每次执行回表操作时都相当于要随机读取一个聚簇索引页面,而这些随机IO带来的性能开销比较大。MySQL中提出了一个名为Disk-Sweep Multi-Range Read (MRR,多范围读取)的优化措施,即先读取一部分二级索引记录,将它们的主键值排好序之后再统一执行回表操作。

4、MySQL在一般情况下执行一个查询时最多只会用到单个二级索引,但存在有特殊情况,也可能在一个查询中使用到多个二级索引,称之为:索引合并,比如Intersection交集合并、Union索引合并等等。

InnoDB引擎的三大特性是什么?

InnoDB的三大特性是:Buffer Pool、自适应Hash索引、双写缓冲区。

自适应Hash索引,InnoDB存储引擎内部自己去监控索引表,如果监控到某个索引经常用,那么就认为是热数据,然后内部自己创建一个hash索引,称之为自适应哈希索引( Adaptive Hash Index,AHI),创建以后,如果下次又查询到这个索引,那么直接通过hash算法推导出记录的地址,直接一次就能查到数据。

InnoDB存储引擎使用的哈希函数采用除法散列方式,其冲突机制采用链表方式。

Buffer Pool,为了提高访问速度,MySQL预先就分配/准备了许多这样的空间,为的就是与MySQL数据文件中的页做交换,来把数据文件中的页放到事先准备好的内存中。数据的访问是按照页(默认为16KB)的方式从数据文件中读取到 buffer pool中。Buffer Pool按照最少使用算法(LRU),来管理内存中的页。

Buffer Pool实例允许有多个,每个实例都有一个专门的mutex保护。Buffer Pool中缓存的数据页类型有: 索引页、数据页、undo页、插入缓冲(insert buffer)、自适应哈希索引、InnoDB存储的锁信息、数据字典信息(data dictionary)等等。

双写缓冲区,是一个位于系统表空间的存储区域,在写入时,InnoDB先把从缓冲池中的得到的page写入系统表空间的双写缓冲区。之后,再把page写到.ibd数据文件中相应的位置。如果在page写入数据文件的过程中发生意外崩溃,InnoDB在稍后的恢复过程中在doublewrite buffer中找到完好的page副本用于恢复。

doublewrite是顺序写,开销比较小。所以在正常的情况下, MySQL写数据page时,会写两遍到磁盘上,第一遍是写到doublewrite buffer,第二遍是从doublewrite buffer写到真正的数据文件中。

它的主要作用是为了避免partial
page write(部分页写入)的问题。因为InnoDB的page size一般是16KB,校验和写入到磁盘是以page为单位进行的。而操作系统写文件是以4KB作为单位的,每写一个page,操作系统需要写4个块,中间发生了系统断电或系统崩溃,只有一部分页面是写入成功的。这时page数据出现不一样的情形,从而形成一个"断裂"的page,使数据产生混乱。

redolog和binlog的区别是什么?

答案见下一题

MySQL崩溃后的恢复为什么不用binlog?

1、这两者使用方式不一样

binlog 会记录表所有更改操作,包括更新删除数据,更改表结构等等,主要用于人工恢复数据,而 redo log 对于我们是不可见的,它是 InnoDB 用于保证 crash-safe 能力的,也就是在事务提交后MySQL崩溃的话,可以保证事务的持久性,即事务提交后其更改是永久性的。

一句话概括:binlog 是用作人工恢复数据,redo log 是 MySQL 自己使用,用于保证在数据库崩溃时的事务持久性。

2、redo log 是 InnoDB 引擎特有的,binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。

3、redo log是物理日志,记录的是“在某个数据页上做了什么修改”,恢复的速度更快;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这的c字段加1 ”,binlog有三种日志记录格式Row、SQL、混合模式。

4、redo log是“循环写”的日志文件,redo log 只会记录未刷盘的日志,已经刷入磁盘的数据都会从 redo log 这个有限大小的日志文件里删除。binlog 是追加日志,保存的是全量的日志。

5、最重要的是,当数据库 crash 后,想要恢复未刷盘但已经写入 redo log 和 binlog 的数据到内存时,binlog 是无法恢复的。虽然 binlog 拥有全量的日志,但没有一个标志让 innoDB 判断哪些数据已经入表(写入磁盘),哪些数据还没有。

比如,binlog 记录了两条日志:

给 ID=2 这一行的 c 字段加1

给 ID=2 这一行的 c 字段加1

在记录1入表后,记录2未入表时,数据库
crash。重启后,只通过 binlog 数据库无法判断这两条记录哪条已经写入磁盘,哪条没有写入磁盘,不管是两条都恢复至内存,还是都不恢复,对 ID=2 这行数据来说,都不对。

但 redo log 不一样,只要刷入磁盘的数据,都会从 redo log 中抹掉,数据库重启后,直接把 redo log 中的数据都恢复至内存就可以了。

MySQL如何实现事务的ACID?

参见下个问题。

InnoDB事务是如何通过日志来实现的?

总的来说,事务的原子性是通过 undo
log 来实现的,事务的持久性性是通过 redo log 来实现的,事务的隔离性是通过读写锁+MVCC来实现的。

事务的一致性通过原子性、隔离性、持久性来保证。也就是说ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔离性)、D(持久性)是手段,是为了保证一致性,数据库提供的手段。数据库必须要实现AID三大特性,才有可能实现一致性。同时一致性也需要应用程序的支持,应用程序在事务里故意写出违反约束的代码,一致性还是无法保证的,例如,转账代码里从A账户扣钱而不给B账户加钱,那一致性还是无法保证。

至于InnoDB事务是如何通过日志来实现的,简单来说,因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo,
然后修改数据页,再记数据页修改的redo。 Redo(里面包括 undo 的修改)
一定要比数据页先持久化到磁盘。

当事务需要回滚时,因为有undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。

更详细的回答是:

redo通常是物理日志,记录的是页的物理修改操作,用来恢复提交事务修改的页操作。而undo是逻辑日志,根据每行记录进行记录,用来回滚记录到某个特定的版本。

当事务提交之后会把所有修改信息都会存到redo日志中。redo日志由两部分组成,一个是在内存里的redo log buffer,另一个是在磁盘里的redo log文件。

mysql 为了提升性能不会把每次的修改都实时同步到磁盘,而是会先存到Buffer Pool(缓冲池)里头,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步。

系统重启后读取redo log恢复最新数据。虽然redo
log会在事务提交前做一次磁盘写入,但是这种IO操作相比于buffer pool这种以页(16kb)为管理单位的随机写入,它做的是几个字节的顺序写入,效率要高得多。

redo log buffer中的数据,会在一个合适的时间点刷入到磁盘中。

这个合适的时间点包括:

1、MySQL 正常关闭的时候;

2、MySQL 的后台线程每隔一段时间定时的讲 redo log buffer 刷入到磁盘,默认是每隔 1s 刷一次;

3、当 redo log
buffer 中的日志写入量超过 redo log buffer 内存的一半时,即超过 8MB 时,会触发 redo log buffer 的刷盘;

4、当事务提交时,根据配置的参数 innodb_flush_log_at_trx_commit 来决定是否刷盘。要严格保证数据不丢失,必须得保证 innodb_flush_log_at_trx_commit 配置为 1。

redo log 在进行数据重做时,只有读到了 commit 标识,才会认为这条 redo log 日志是完整的,才会进行数据重做,否则会认为这个 redo log 日志不完整,不会进行数据重做。

undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。当执行回滚时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

而事务的隔离性,也可以通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,帮助用户实现一致性非锁定读取,这也是MVCC的实现机制的组成部分。

什么是当前读和快照读?

当前读

像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。是一种悲观锁的实现。

快照读

像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC。

什么是MVCC?

MVCC
(Multi-Version Concurrency Control) ,叫做基于多版本的并发控制协议。他是和LBCC(Lock-Based Concurrency
Control)基于锁的并发控制概念是相对的。MVCC是乐观锁的一种实现方式,它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本。

MVCC最大的好处:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能,现阶段几乎所有的RDBMS包括MySQL,都支持了MVCC。

MVCC的底层实现原理是什么?

MVCC实现原理主要是依赖记录中的隐式字段,undo日志
,Read View 来实现的。

MySQL中每行记录除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段。DB_TRX_ID是最近修改(修改/插入)事务ID,记录创建这条记录/最后一次修改该记录的事务ID。DB_ROLL_PTR,回滚指针,用于配合undo日志,指向这条记录的上一个版本。

不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,也就是版本链。

事务进行快照读操作的时候产生一个Read
View,记录并维护系统当前活跃事务的ID,因为当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大。

Read View主要是将要被修改的数据的最新记录中的DB_TRX_ID(即当前事务ID)取出来,与系统当前其他活跃事务的ID去对比(由Read View维护),如果DB_TRX_ID跟Read View的属性做了某些比较,不符合可见性,那就就通过DB_ROLL_PTR回滚指针去取出Undo Log中的DB_TRX_ID再比较,即遍历链表的DB_TRX_ID(从链首到链尾,即从最近的一次修改查起),直到找到满足特定条件的DB_TRX_ID, 那么这个DB_TRX_ID所在的旧记录就是当前事务能看见的最新老版本。

RC,RR级别下Read View生成时机的不同,造成RC,RR级别下快照读的结果的不同。RC隔离级别下,是每个快照读都会生成并获取最新的Read View,也就是说事务中,每次快照读都会新生成一个快照和Read View, 这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因;而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View,快照读生成Read View时,Read View会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见。

什么是锁?MySQL 中提供了几类锁?

锁是实现数据库并发控制的重要手段,可以保证数据库在多人同时操作时能够正常运行。MySQL 提供了全局锁、行级锁、表级锁。其中 InnoDB 支持表级锁和行级锁,MyISAM 只支持表级锁。

什么是全局锁、共享锁、排它锁?

全局锁就是对整个数据库实例加锁,它的典型使用场景就是做全库逻辑备份。 这个命令可以使整个库处于只读状态。使用该命令之后,数据更新语句、数据定义语句、更新类事务的提交语句等操作都会被阻塞。

共享锁又称读锁 (read lock),是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。当如果事务对读锁进行修改操作,很可能会造成死锁。

排他锁 exclusive lock(也叫 writer lock)又称写锁。

若某个事物对某一行加上了排他锁,只能这个事务对其进行读写,在此事务结束之前,其他事务不能对其进行加任何锁,其他进程可以读取,不能进行写操作,需等待其释放。排它锁是悲观锁的一种实现。

若事务 1 对数据对象 A 加上 X 锁,事务 1 可以读 A 也可以修改 A,其他事务不能再对 A 加任何锁,直到事物 1 释放 A 上的锁。这保证了其他事务在事物 1 释放 A 上的锁之前不能再读取和修改 A。排它锁会阻塞所有的排它锁和共享锁。

MySQL中的表锁有哪些?

MySQL 里表级锁有两种:普通表级锁、元数据锁(meta data lock)简称 MDL和AUTO-INC锁。表锁的语法是 lock tables t read/write。

可以用 unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。

对于 InnoDB 这种支持行锁的引擎,一般不使用 lock tables 命令来控制并发,毕竟锁住整个表的影响面还是太大。

MDL:不需要显式使用,在访问一个表的时候会被自动加上。

MDL 的作用:保证读写的正确性。

在对一个表做增删改查操作的时候,加 MDL
读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

读锁之间不互斥,读写锁之间,写锁之间是互斥的,用来保证变更表结构操作的安全性。

AUTO-INC锁,也就是在执行插入语句时就在表级别加一个AUTO-INC锁,然后为每条待插入记录的AUTO_INCREMENT修饰的列分配递增的值。

InnoDB引擎的行锁是怎么实现的?

InnoDB是基于索引来完成行锁,在锁的算法实现上有三种:

· Record lock:单个行记录上的锁

· Gap lock:间隙锁,锁定一个范围,不包括记录本身

· Next-key lock:record+gap 锁定一个范围,包含记录本身

Gap锁设计的目的是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生,innodb对于行的查询使用next-key lock,Next-locking keying是Record lock和Gap lock的组合。当查询的索引含有唯一属性时,将next-key lock降级为record key。

有两种方式显式关闭gap锁 ,第一种. 将事务隔离级别设置为RC ;第二种. 将参数innodb_locks_unsafe_for_binlog设置为1。

谈一下MySQL中的死锁

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。

如何查看死锁?

使用命令 show engine
innodb status 查看最近的一次死锁。

InnoDB Lock
Monitor 打开锁监控,每 15s 输出一次日志。使用完毕后建议关闭,否则会影响数据库性能。

对待死锁常见的两种策略:

通过 innodblockwait_timeout
来设置超时时间,一直等待直到超时;

发起死锁检测,发现死锁之后,主动回滚死锁中的某一个事务,让其它事务继续执行。

简述下MySQL8中的新增特性有哪些

MySQL8在功能上的我们需要关注增强主要有:1、账户与安全;2、索引3、InnoDB 增强。

主要表现在:

1、用户的创建与授权需要两条单独的SQL语句执行。认证插件更新。密码管理和角色管理发生变化。

2、隐藏索引,被隐藏的索引不会被优化器使用,但依然真实存在,主要用于软删除,可以根据需要后续真正删除或者重新可视化。

开始真正支持降序索引,以往的MySQL虽然支持降序索引,但是写盘的时候依然是升序保存。MySQL8.0中则是真正的按降序保存。

不再对group by操作进行隐式排序。

索引中可以使用函数表达式,创建表时创建一个函数索引,查询的时候使用同样的函数就可以利用索引了。

3、原子ddl操作,MySQL5.7执行drop命令 drop table
t1,t2; 如果t1存在,t2不存在,会提示t2表不存在,但是t1表仍然会被删除,MySQL8.0执行同样的drop命令,会提示t2表不存在,而且t1表不会被删除,保证了原子性。

自增列持久化,解决了之前的版本,主键重复的问题。MySQL5.7及其以前的版本,MySQL服务器重启,会重新扫描表的主键最大值,如果之前已经删除过id=100的数据,但是表中当前记录的最大值如果是99,那么经过扫描,下一条记录的id是100,而不是101。MySQL8.0则是每次在变化的时候,都会将自增计数器的最大值写入redo log,同时在每次检查点将其写入引擎私有的系统表。则不会出现自增主键重复的问题。

你可能感兴趣的:(架构师进阶-性能调优,mysql,数据库)