MySQL逻辑架构

所有跨存储引擎的功能都在服务器层实现

存储引擎负责MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信,存储引擎API包含十几个底层函数,用于执行诸如“开始一个事务”,“根据主键提取一行记录”等操作,但存储引擎不会解析sql(InooDB是个例外,它会解析外键定义,因此MySQL本身没有实现这个功能)

优化器会解析查询,并创建内部数据结构(解析树),对其进行各种优化,包括重写查询,决定表的读取顺序,如何选择合适的索引等。可以通过(hint)提示优化器使用哪个索引,以及(explain)解释优化过程的各个因素。优化器不关心存储引擎,但存储引擎对于优化查询是有一定影响的

并发控制

读写锁主要解决的是并发问题,试想一下如果两个进程同时对一个邮箱投递邮件,会发生什么情况?显然邮箱的数据就会被破坏,但是如果通过锁来处理,客户每次投递邮件,该邮件已经被其他用户锁定了那就必须等待,直到锁释放才能进行投递,这样就对并发进行了控制。但是只有一个进程可以修改邮箱的数据这在大容量或者大并发的系统中是不理想的。

MySQL通过两种类的锁来解决上述问题:

实际情况中并发读是不会有什么问题的,因为读取不会修改数据,但是如果在读的过程中目标数据发生了修改,产生的结果是不确定的。

  • 读锁(共享锁)是共享的,相互不阻塞,相互不干扰,排序位置永远在写锁之后。
  • 写锁(排他锁)是排他的,也就是说它会阻塞所有的写锁和读锁,在写锁没有结束前读锁是需要排队的直到写锁释放,才能继续读取。只有这样才能防止用户读取到正在修改的数据(中间值)。

在实际数据库系统中,每时每刻都在发生锁定!

锁粒度

提高共享资源的并发性的方式就是让锁定对象更有选择性。尽量只锁定需要修改的部分数据,而不是所有的资源是最好的。

MySQL实现的方式了两种粒度的锁(都只在存储引擎中实现)

  • 行锁:最大程度地支持并发处理(同时也带来了最大的锁开销)
  • 表锁:开销最小,粒度最大,并发处理能力越弱。

事务

MySQL事务默认是自动提交的,也就是说每一个查询都被当作一个事务执行提交操作。

事务就是一组独立的工作单元,是一个整体。事务的运作需要更强的CPU处理能力,更大的内存和更多的磁盘空间,也就是说对于一些不需要事务的查询类应用,选择一个非事务的存储引擎可以获得更高的性能。

ACID:

  • 原子性: 事务是最小的工作单元,不可再分。
  • 一致性: 事务保证多条DML语句同时成功或者同时失败。
  • 隔离性: 并发环境下事务具有隔离性,每个事务都有各自完成的数据空间。
  • 持久性: 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
 

隔离性(隔离级别):

  • 读未提交:读到的都是对方事务未提交的数据脏读
  • 读已提交:读的都是对方事务提交的数据,存在不可重复读现象(一个事务对同一行数据重复读取两次,但是却得到了不同的结果)
  • 可重复读:事务在启动时看到的数据,和在执行过程中看到的是一致的,不会被更改。但是有可能会读到其他事务新增的数据,也就是可能会导致幻读
  • 序列化读/串行读:需要排队,效率低,解决所有的问题。

事务隔离级别越高,在并发下会产生的问题就越少,但同时付出的性能消耗也将越大。

存储引擎

InnoDB对于百分之95的用户都是最佳的选择,花时间研究它准没错了。

InnoDB

设计用来处理大量的短期事务的一种引擎。

InnoDB的表是基于聚簇索引建立的。聚簇索引对主键查询有很高的性能,不过它的二级索引(非主键索引)是必须包含主键列的。所以主键列很大的话,其他所有索引都很大。

InnoDB采用两阶段锁定协议。在事务执行过程中随时都可以锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻被释放的。InnoDB会根据隔离级别在需要的时候自动加锁。

InnoDB的MVCC

基于提升并发性的考虑,InnoDB实现了多版本并发控制(MVCC)可以认为是行锁的一个变种,可以使大多数读操作都可以不用加锁。

怎么实现的呢?

  • InnoDB的MVCC是通过每行记录保存两个隐藏的列来实现,这两个列分别保存了行的创建时间以及过期时间,以版本号的形式进行显现。
  • select:
    • InnoDB只查找早于当前事务版本的数据行,这样就可以保证读取的行要么是事务开始前存在的,要么是事务自身插入的或者修改过的。
    • 行的删除版本要么未定于,要么大于当前版本号。这可以保证当前读取的行是事务开始之前未删除的
  • insert:
    • 新插入的每一行保存最新系统版本号
  • delete:
    • 保存最新系统版本号为删除标识
  • update:重新插入一遍新的数据,之前的数据添加删除版本号

这样的设计使读数据操作更简单,性能更好,而且也能保证只会读取到符合标准的行。代价就是每行记录都需要额外的存储框架,需要做一些维护工作。

Archive引擎

只支持INSERT和SELECT操作,不支持索引,每次SELECT操作都是全表扫描,适合日志以及数据采集类的应用。

 

posted @ 2022-04-17 18:58  猫长寿  阅读(24)  评论(0编辑  收藏  举报