MySQL 的逻辑结构

先看看 MySQL 逻辑结构图吧
MySQL 逻辑结构图

连接管理与安全性

每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行,该线程只能轮流在某个 CPU 核心或 CPU 中运行,服务器会负责缓存线程,因此不需要为每一个新建的连接创建或销毁线程

优化与执行

  1. MySQL 会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化、包括重写查询、决定表的读取顺序,以及选择合适的索引等。
  2. 优化器并不关心表使用的是什么存储引擎,但存储引擎对于优化查询是有影响的。

并发控制

每种 MySQL 存储引擎都可以实现自己的锁策略和锁粒度。

读写锁

  1. 共享锁(shared lock),也称为读锁(read lock)。读锁是共享的,或者说是项目不阻塞的。多个客户在同一时刻可以同时读取同一个资源。
  2. 排他锁(exclusive lock),也称为写锁(write lock)。写锁则是排他的,一个写锁会阻塞其他的写锁和读锁。

锁粒度

一种提高共享资源并发性的方式就是让锁定对象更有选择性。尽量修改部分数据,而不是所所有资源。更理想的方式是,只队会修改的数据片进行精确的锁定。任何时候在给定的资源上,锁定的数据量越少,则系统的并发程度更高,只要相互之间不发生冲突。

锁策略

锁策略就是在开销和安全性之间寻求平衡 ,这种平衡会影响性能

  1. 表锁(table lock)
    1. 表锁是 MySQL 中最基本的锁策略,并且是开销最小的策略
  2. 行级锁(row lock)
    1. 行级锁可以最大程度地支持并发处理(同时也带来了最大的开销)
    2. 行级锁只在 MySQL 的存储引擎层实现

事务

ACID 特性

  1. 原子性:一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有的操作要么全部提交成功,要么全部失败回滚
  2. 一致性:数据库总是从一个一致性的状态转换到另一个一致性的状态
  3. 隔离性:一个事务的操作对另一个事务时不可见的
  4. 持久性:事务一旦提交,所作的修改就会保存到数据库中

隔离级别

每一种级别都规定了一个事务中所作的修改,哪些在事务内和事务间可见的,哪些时不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。

可以通过 SQL 改变事务的隔离级别:SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
也可以更改配置文件,对整个数据库设置隔离级别。

四种隔离级别:

  1. READ UNCOMITTED(未提交读):在 READ UNCOMMITTED 级别,事务中的修改,即使没有提交,对其他事务也都是可见的
  2. READ COMMITTED(提交读):一个事务开始之前只能获取已提交事务的所做更改(事务对其他事务不可见)
  3. REPEATABLE READ(可重复读):保证了在同一个事务中多次读取同样的记录的结果是一只的。但是理论上,可重复读隔离界别还是无法解决另外一个幻读的问题
    • 幻读:指的是当某个事务在读取某个范围的内数的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围内的记录时,另外一个事务又在该范围内插入了新的记录
  4. SERIALIZABLE(可串行化):这种隔离级别是最高的;通过强制事务串行执行,避免了幻读的问题;SERIALIZABLE 会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题

死锁

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

事务日志

可以帮助提高事务的效率

MySQL 中的事务

MySQL 提供两中事型的存储引擎: InnoDB 和 NDB Clister

自动提交(AUTOCOMMIT):

查询自动提交的命令:SHOW ARIABLES LIKE ‘AUTOCOMMIT’;
设置 AUTOCOMMIT : SET AUTOCOMMIT=1;
1 或者 ON 表示启用,0 或者 OFF 表示禁用。

  1. MySQL 默认采用了自动提交模式
  2. 当 AUTOCOMMIT 被禁用时,需采用显式的方式进行提交(COMMIT)或者回滚(ROLLBACK)
显示和隐式锁定
  1. 显示锁定——在执行 SQL 时加入 LOCK TABLES 或者UNLOCK TABLES 进行锁定和释放(不推荐)
  2. 隐式锁定——在事务执行过程中,随时都可以执行锁定,锁只有在 COMMIT 或 ROLLBACK 时才会释放,并且在锁在同一时刻被释放

MVCC —— 多版本并发控制

MVCC 是通过保存数据在某个时间点的快照来实现。
在 InnoDB 存储引擎中,是通过在每行记录的后面保存两个隐藏的列来实现的。(这两个列分别存储了行的创建时间和行的过期时间(或删除时间),即为系统版本号)。

  1. 对隔离级别的支持
    1. REPEATABLE READ
      1. SELECT:InnoDB 会根据两个条件检查每行记录,符合条件才能返回查询结果
      2. INSERT:InnoDB 为新插入的记录板寸当前系统版本号作为行版本号
      3. DELETE:InnoDB 为删除的记录保存当前系统版本号作为行删除标识
      4. UPDATE:InnoDB 会插入的新纪录,保存当前系统版本号,同时保存当前系统版本号到原来的行作为删除标识
    2. READ COMMITTED
  2. 不支持的给级别
    1. READ UNCOMMITTED:因为此隔离级别总是读取最新的数据行,而不符合当前事务版本的数据据行
    2. SERIALIZABLE:因为此隔离级别会对读取行加锁

存储引擎

在文件系统中,MySQL 将每个数据库保存为数据目录下的子目录;创建表时,MySQL 会在数据库的子目录下创建一个和表名一样的 .frm 文件保存表的定义。可以使用 SQL 查询表的信息 SHOW TABLE STATUS LIKE 'TABKENAME'

MySQL 内置多种存储引擎,而这里只介绍两种:InnoDB 和 MyISAM

InnoDB 存储引擎

InnoDB 是 MySQL 的默认事务性存储引擎,也是最重要的,使用最广泛的存储引擎。它被设计用来处理大量的短息事务。

InnoDB 储存引擎是将数据存储在表空间中,表空间是由 InnoDB 管理的一个黑盒子,有一系列的数据文件组成。

InnoDB 采用了 MVCC 来支持高并发,并且实现四个标准的隔离级别,其默认的隔离级别是 REPEATABLE READ ,并且通过“间隙锁”策略防止出现幻读。

注:间隙锁使得 InnoDB 不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,防止幻读的出现

MyISAM 存储引擎

MyISAM 提供了大量的特性,包括全文引擎、压缩、空间函数等,但 MyISAM 不支持事务和行级锁,而且有一个毫无疑问的缺陷就是崩溃后无法保存数据的安全恢复。

  1. 在存储方面, MyISAM 会将表存储在两个文件中,分别为数据文件和索引文件(.MYD 和 .MYI)
  2. 特性
    1. 加锁与并发:对整张表加锁,而不是针对行。读取时会对需要读到的表加共享锁,写入时则对表加排他锁。但是在表有读取查询的同时,也可以往表中插入新的记录。
    2. 修复:对于 MyISAM 表,MySQL 可以手工或者自动执行检查和修复操作,这里修复和事务恢复以及崩溃时不同的概念。执行表的修复可能会导致一些数据丢失,而且修复操作时非常慢的。
    3. 索引特性:对与长字段类型 BLOB 和 TEXT 等,可以基于其前 500 个字符创建索引。也支持全文索引。
    4. 延迟更新索引键:创建 MyISAM 表时,如果指定了 DELAY_KEY_WRITE 选项,在每次修改执行完成时,不会立刻将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区,只有在清理键缓冲区或关闭表的时候才会将对应的索引写入磁盘。
  3. 压缩表——在创建表并导入数据之后,不会被修改,可以使用 myisampack 对 MyISAM 表进行压缩。因为不能被修改,如果一定要修改,则需要先解压,修改之后再压缩。压缩表可以极大的减少磁盘空间的占用,因此也可以减少磁盘 I/O ,从而提升查询性能。压缩表也支持索引,但索引只能是只读恶的。

MySQL 其他存储引擎

除了上边描述的连个存储引擎外,MySQL 还支持:

  1. Archive 引擎
  2. Blackhole 引擎
  3. CSV 引擎
  4. Memory 引擎
  5. Merge 引擎
  6. … …

这里不过多的赘述了……

最后更新: 2019年12月01日 00:00

原始链接: https://maiyikai.github.io/2019/11/11/1573376841/

× ~谢谢大爷~
打赏二维码