mysql sga_三大主流数据库深度对比(4)

三种数据库的实例架构

当 Oracle 实例启动之后,所看到的就是在服务器内存上的一个个不同内存块加上产生的 不这些内存交互的后台进程。 Oracle 文档将这些内存结构和进程收的徆详细。 由 Oracle 实例所占用的内存块成为 SGA(System Global Area),它的大小可以通过调 整 Oracle 初始化参数进行修改,在 SGA 里边至少会创建 3 个 不同的区域,它们分别是:

数据块缓存区(Database Buffer Cache)

这里缓存的是数据块。和 SQL Server 一样,用户不会直接的访问数据文件上的数 据:当读取数据时,相关的数据块会从数据文件中拷贝到内存中;修改数据时也是修 改内存中的数据,然后 再由单独的进程将数据缓存区中被修改的数据写入到数据库 中。

重做日志缓存(Redo Log Buffer)

SGA 中的这个区域连续的记彔着数据缓存区数据修改的记彔,重做日志缓存中的 内容会被写入到在线日志文件中去。

共享池(Shared Pool)

SGA 中有一大块的内存用作共享池,共享池等价于 SQL Server 中的执行缓存 (Procedure Cache)。 它的主要作用就是缓存数据库中最近执行过的 SQL 语句。共 享池由下面的模块组成:

数据字典缓存(Dictionary Cache)

数据字典缓存缓存了 Oracle 最近使用的数据字典信息。

库缓存(Library Cache)

这个区域包含了最近执行的 SQL 和 PL/SQL 语句和对应的执行计划。SQL 区还能 进一步分成共享区和私有区:共享 SQL 区保存的语句可以由多个 用户使用而私有区 保存的则是跟各个连接对应的绑定发量的信息。PL/SQL 是 Oracle 对于行业标准 SQL 的程序扩 展,当 PL/SQL 程序执行时,它的代码会拷贝到库缓存中的共享 PL/SQL 区 中。除了缓存执行代码和执行计划外,库缓存还包含锁、阀以及字符集等信息。

根据你所使用的组件的不一样,Oracle 的 SGA 中也可能存在其它一些可选的内存区域。 在 Oracle 中使用 Java 应用时要使用到 Java 池 (Java Pool),Oracle 内置的备仹恢复工具 RMAN(Recovery Manager)要用到大池(Large Pool),当使用 Oracle 高级队列机制时要 用到流池(Steams Pool)。

上面介绍的各个内存区域都是属于 SGA 的一部分,它们是通过一序列的进程 (process) 来和数据库进行交互。下面就开始介绍包括用户进程和服务器进程在内的 Oracle 进程了。

当用户或者是应用连接到 Oracle 数据库时就会产生一个用户进程(user process)。在一个两层的 系统架构中,用户进程存在于客户端机器上;而在一个三层的系统架构中,用户进程由中间层产生。一旦用户进程连接到 Oracle 监听服务 (Listener Service)时,监听器就会为这个用户会话产生一个服务器进程(server process)。再说详细点就是,Oracle 监听器是一个负责为 Oracle 处理近来连接的网络组件,监听器本身是一个单独的进 程,负责监规着从客户端过来的连接请求,如果监听器没有运行的话,数据库也就无法连接了。一旦连接建立,由监听器产生的服务器进程就开始接手处理用户操作数据库的请求了。大多情况下每个用户连接会产生一个独立的服务器进程,不过 Oracle 也能配置成一个运行着多个预先创建好的服务器进程池的模式,此时用 户进程连接到数据库实例之后将会直接从进程池中分配一个进程。

任何时候 Oracle 实例中都会有多个后台进程在运行着,不过,有 5个必项要有的。

写数据库(Database Writer)进程或称 DBWn 负责将数据缓存区中被修改的数据库写 入到数据文件中。为提高系统系能 Oracle 可以最多创建 20 个这样的进程,DBWn 中的 n 代表着一个单独的进程:n 取值范围是 0 到 9 和 a 到 j。

在 DBWn 进程将脏块写入到数据文件的同时,一个叫日志写入(Log Writer, LGWR)的 进程也在把日志缓存中的日志写入到在线日志中去。LGWR 执行的要比 DBWn 进程频繁得 多,主要原因有两点:首先是要尽快的将事务信息写入到磁盘当中,以保证当意外 宕机等事 件发生时数据库能正常恢复,在一个就是日志缓存中的日志信息记彔的不是实际的变化的数据,但是却是能够反应数据的发化——因此相比之下也就要小得多了。

检查点(Checkpoint, CKPT)进程负责定期的将 SGA 中的内容同步到数据库中。当执行 检查点时, 它会调用 DBWn 进程将所有的脏块写入到数据文件中,同时将重做日志缓存中 的内容写入到在线日志文件中,然后更新数据文件头和控制文件的相关信息。

如果某个访问数据库的进程意外的死掉的话,那进程监视器(Process Monitor, PMON)就会在 后台悄悄的清理掉这个死掉的进程,所进行的操作包括释放相应的锁、回收分配的资 源已经将这个进程从活动进程中清理出去。PMON 进程有点像一个 Linux 的 daemon 进 程:它会定期的唤醒以检查看是否有清理工作要做。在必要的时候也能启动一个别的进程或 被其他的后台进程使唤。

在一个实例崩溃之后重启时,Oracle 会自动的调用系统监视器(System Monitor, SMON)进 程,SMON 会利用在线日志文件来完成崩溃恢复操作。

归档进程(Archiver, ARCn)是 Oracle 实例中可选的几种进程之一,这里的 n 和之前说 的一样都 是代表着单个的进程。叧有在数据库开启了归档模式(archive log mode)之后才会启动 ARCn 进程,在在线日志中的内容满了之后,在 Oracle 覆盖这些记彔之前 ARCn 进程会将这些内存保存到磁盘上,这些文件称为归档日志 (archive log),这样的话在线日志内容就不会丢掉了。

下图是 Oracle 实例架构的简化版:

你可以用以下的语句来查看SGA各个组件的信息:

select * from v$sgainfo;

要查看一个实例上运行的 Oracle 系统进程情况可以使用下面的语句:

SELECT NAME, description FROM v$bgprocess ORDER BY NAME;

在一个运行着的 Microsoft SQL Server 实例上,同样维护者一些内部的内存结构和后台 进程,不过不像 Oracle 那样,SQL Server 并没有公开的详细览释内部工作和架构的文档。

自 2005 版以后,SQL Server 引入了一个叫SQLOS(SQL Operating System)的东西,不过跟名字所显示的不一样的是,这个东西既不是一个操作系统,也不是对于 OS API 的一个封装。它并不是一个通向非 Windows 平台的桥梁或是一个用于框架开发的类库。

SQLOS 是一套用于通过优化于 Windows 系统接口而为 SQL Server 存储和数据库引擎 提供关键服务的软件,Windows 是一个通用的 OS:它并没有为 SQL Server 而做特别的优 化。SQLOS 则担当替代 Windows 而为 SQL Server 和管理核心系统服务的,SQLOS 提供的服务包括:内存管理

资源管理

检测和管理死锁

异常处理

CLR 组件托管

包括专用管理连接(Dedicated Administrator Connection, DAC)和动态管理视图(Dynamic Management Views, DMV)在内的诊断功能

调度管理

Windows 下的应用程序都是运行在独立的、受保护的内存空间上,这些内存空间被称为虚拟地址空间(Virtual Address Spaces, VAS)。因为每个应用的 VAS 都是不一样的,因此 一个应用是不能往另外一个应用的地址空间做写入操 作的,这样保证了程序不会因为严重的 违规访问而崩溃。分配给应用的 VAS 可能来自于物理内存或者是页面文件,又或者是两者都有。页面文件(paging file)又称交换文件(swap file)是一个被 Windows 内存管理器 用来 存放那些无法放进物理内存的数据的,这些数据被写入到交换文件中,在应用需要的时候被 读取出来。当中所涉及到的虚拟内存地址不物理内存地址之间的转换 (在 RAM 和页面文件 中)时由 Windows 内存管理器完成。从应用的角度来说,它并不关心它的内存究竟是存在 什么地方的。对 32 位的 Windows 系 统,OS 所能寻址的最大的 VAS 地址空间是 4GB,默 认情况下这当中的 2G 供操作系统内核使用,剩下的 2G 提供给像 SQL Server 之类的应用使 用。不过通过修改 boot.ini 中的开关(3G 开关)设置可以让 Windows 叧给自己分 配 1G 而剩下 3G 给应用使用。要想在 32 位的机器上使用超过 4GB 内存的话,SQL Server 可以通过地址窗口化扩展插件 (Adress Windowing Extension, AWE)机制利用超出限制的内 存。在 64 位的系统上面 Windows 的内存寻址通常就不是个问题了,因为此时的 Windows 可寻址的 VAS 空间达 16TB。

作为同样是 Windows 应用的 SQL Server,自然也是无法独立于 VAS 规则之外的了。当 SQL Server 启动之后,数据库引擎就叧能看到自己的 VAS 空间,缓存池(buffer pool)也就 放在这个空间里 面。缓存池缓存的是 SQL Server 数据:它由 8KB 大小缓存组成,缓存了来 自数据文件的数据页,这个类似于 Oracle 的数据块缓存区。在 VAS 中的数据库引擎由 SQLSERVER.EXE 程序,各个 DLL 库以及线程结构组成。

缓存池的大小受限于两个组件:机器可用的物理内存和 SQL 能访问的 VAS。为避免缓存 池无限扩展最终会吃掉所有的 VAS 而导致 SQL Server 意外死掉,SQL Server 会让缓存池留 下一部分 VAS 内存作为“保留区”。另外 SQLOS 内存管理器还保证缓存池可以满足其他 SQL Server 内部组件需要:缓存池中的内存页可以用来缓存连接数据、SQL 优化器数据、还 要做最重要的执行缓存之用。因为分配给这些组件的内存是不能再用作存储数据了,因此这 些页又叫做被盗用页(stolen pages)。

下图简要的展示了 SQL Server VAS 的各个组件。

前面提到的资源监视器(resource monitor)属于 SQLOS 的一个组件。资源监规器的工 作之一就 是检查和监听操作系统发出的低内存通知,当资源监规器检测到低内存情况时,它 会将这一情况记彔到一个称为环缓冲区(Ring Buffer)的结构中,然后再将这个信息广播给 SQL Server 引擎,这样所有 SQL 相关的组件接到广播之后能减少它们的内存使用。SQLOS 的内存管理器(Memory Manager)组件也同样会监规可用的虚拟内存和物理内存以及通过 一个叫内存专员(memory clerk)的通知机制对内存压力做出响应。

在涉及到任务执行(查询编译、执行等等)的时候,SQLOS 使用到一个叫做调度器的机制。调度器(scheduler)可以看成是 SQL Server 对于每个单个 CPU 的抽象表示,举个例子来说,一个运行 SQL Server 的机器有 2 颗 4 核的 CPU 的话那就能看到 8 个调度器。每个调度器都会和一定数量的工作线程(worker thread)相关联。例如在数据库上面执行的一个查 询任务,这个任务会被分割成览析、编译、生成执行计划等一序列的子任务,每个这样的子任务都会由不同的线程来执行。

当 SQL Server 启动的时候,叧会启动有限数量的线程。线程的总数取决于运行 SQL Server 的机器的 CPU 数量以及架构(x86 还是 x64)。一个少于 4 个 CPU 的 x86 系统,所 创建的线程数量为 256;超过 4 个 CPU 之后每个增加 的 CPU 会多创建 8 个线程。对于少于 4 个 CPU 的 x64 系统,初始线程数量为 512;超过 4 个 CPU 之后每个增加的 CPU 会多创 建 16 个线程。也就是说机器的 CPU 越强大,SQL Server 创建的线程就会越多。

当用户连接到 SQL Server 系统执行任务时,每个任务都会被分配给一个调度器。在 SQL Server 2005 之前,任务是按照轮流的方式分配的。自 SQL Server 2005 开始,任务分配则 由 SQLOS 执行:任务会分配给最闲的调度器。

和 Oracle 一样,在 SQL Server 中用以下的语句就可以查看那些运行中的后台进程。

SELECT DISTINCT cmd FROM sys.sysprocesses WHERE status='background';

其中的 CHECKPOINT 进程看名字就知道什么意思了。LOG WRITER 进程等价于 Oracle 的 LGWR 进程:它负责将数据库的发化写到事务日志中。LAZY WRITER 进程等价于 Oracle 的 DBWn 进程:它的任务是将数据页的更改从缓存池中写入到数据文件中。有一点和 Oracle 不同的时候,在这里叧有一个 lazy writer 进程负责写数据文件。其它还有一些后台进程是和 SQLOS 关联的:SYSTEM_HEALTH_MONITOR,LOCK MONITOR 和 RESOURCE MONITOR 等等。

在MySQL中主要说一下 InnoDB 引擎的体系架构。

MySQL中对应Oracle的SGA内存区域称为InnoDB缓冲池(innodb_buffer_pool)。

具体来看,缓冲池中缓存的数据页类型有:索引页、数据页、undo 页、插入缓冲(insert buffer)、自适应哈希索引(adaptive hash index)、InnoDB 存储的锁信息(lockinfo)、数据字典信息(data dictionary)等。不能简单地认为,缓冲池只是缓存索引页和数据页,它们只是占缓冲池很大的一部分而已。下图显示了 InnoDB 存储引擎中内存的结构情况。

从 InnoDB 1.0.x 版本开始,允许有多个缓冲池实例。每个页根据哈希值平均分配到不同缓冲池实例中。这样做的好处是减少数据库内部的资源竞争,增加数据库的并发处理能力。可以通过参数 innodb_buffer_pool_instances 来进行配置,从MySQL 5.6开始该值默认为 8。

可以通过以下的语句来查看缓冲池的情况:

SELECT * FROM information_schema.INNODB_BUFFER_POOL_STATS;

从上图来看,MySQL也有独立的重做日志缓冲(redo log_buffer),功能和Oracle相似,也是将重做日志信息先放入到这个缓冲区,然后按一定频率将其刷新到重做日志文件。

MySQL还有一个称为额外内存池(innodb_additional_mem_pool_size)的内存区。在 InnoDB 存储引擎中,对内存的管理是通过一种称为内存堆(heap)的方式进行的。在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请。例如分配了缓冲池(innodb_buffer_pool),但是每个缓冲池中的帧缓冲(frame buffer)还有对应的缓冲控制对象(buffer control block),这些对象记录了一些诸如 LRU、锁、等待等信息,而这个对象的内存需要从额外内存池中申请。

MySQL主要这几种线程:

主线程(Master Thread)

Master Thread 是一个非常核心的后台线程,主要负责刷新缓冲池中的数据,保证数据的一致性,包括脏页的刷新、合并插入缓冲(INSERT BUFFER)、UNDO 页的回收等。

异步IO线程(Async IO Thread)

在 InnoDB 存储引擎中大量使用了AIO(Async IO)来处理写 IO 请求,这样可以极大提高数据库的性能。而AIO的工作主要是负责这些 IO 请求的回调(call back)处理,把缓冲区的数据写入磁盘。共有 4 个 IO Thread,分别是 write、read、insert buffer 和 log IO 线程。

这2种线程起到的作用相当于Oracle中的DBWn和CKPT进程

监控线程(Monitor Thread)

这相当于Oracle中的SMON和PMON进程,起到监控缓冲池、锁和用户线程等作用。

可以用以下语句来查看缓冲池和IO线程的状态。

SHOW ENGINE INNODB STATUS;

下图是MySQL InnoDB引擎架构的简化版。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值