《Anatomy of a Database System》这篇发表于87年、一共48页的论文据说是DBA入门必看,但是找了全网没有找到中文翻译。这篇文章对关系型数据库确实有提纲挈领的作用,看完能带来融会贯通的感觉,值得抄写一遍,如有任何抄写不当的地方请诸位看官留言。

1. 文章结构

 
文章把数据库划分为4块,chap2、4、5、6都对应上图每一块;chap3浅显的讲了磁盘存储的设计。
 
 

2. Process Manager

这一章讲数据库的并发模型,稍微翻下chap2的图片就能明白,下面只简要贴出自己感兴趣的部分:

2.1 各并发模型对比

2.2 线程间传递数据

理想的服务器处理架构有非阻塞异步I/O、有dispatcher threads将客户端连接分发给worker threads,这就引来一个问题:数据如何在进程货线程间传递?答案通常是:使用buffer。

buffer类型  描述  
Disk I/Obuffer

1. 来自DB的I/O请求:缓冲池
缓冲池是堆内数据结构,所有数据库都有缓冲池。刷盘时,线程生成包含当前页frame地址、空frame指针的I/O请求,实际刷盘、读到缓冲池的操作都是一步的
2. 日志文件I/O请求:log tail
数据库事务执行过程中日志被写在log tail内存队列里,由FIFO顺序随机(比如事务提交/事务组提交触发、log buffer满触发、DML触发等)刷入磁盘。

 
Client communication buffer

适用于pull模型,客户端主动拉取。一笔查询的worker thread包含指向结果队列的指针:
1. 每个客户端连接有一个socket,则worker线程引用socket内队列;
2. 客户端连接与网络socket多对多,则为每个client维护一个通信队列(放SQL结果),并有一个专门的调度agent处理来自client的fetch请求。

 

2.3 数据库线程与OS处理器的映射

大多数DB起源于70年代,商业化于80年代,很多OS特性在当时是不支持的,例如文件系统缓冲控制、异步I/O;还有就是以前的OS线程包并不高效。出于这些历史遗留、移植性、性能等考虑,很多DB自己做了操作系统应该做的事情,例如非阻塞的异步接口(用来处理慢任务如I/O)、事件流编程、任务切换、线程状态管理、调度等。然而,使用DB级的线程包引出一些设计问题:给定的DB线程组,应该有多少个OS处理器?那些DB任务需要有单独的线程?如何给线程分配处理器?

为了讨论以上问题,首先将问题简化为:只有DB线程和OS处理器两个单元参与、没有OS线程支持的情况。这种情况下DB包含以下处理器:

  1. 1-n个processes给SQL处理线程,通常dba可调。
  2. 1-n个dispatcher processes。监听网络端口、分发连接请求给其他process的线程、为连接创建session,通常dba可调。
  3. 与数据库磁盘数对应的I/O proccesses。如果OS不支持异步I/O,需要数据库为每个数据库磁盘起一个process来处理I/O请求。
  4. 与log磁盘数对应的I/O processes。如3。
  5. 与client session数对应的调度器代理process。有的系统中,需要为client session分配一个处理器来维护session状态、处理客户通信;有的系统中,不需要分配处理器,有单独的数据结构供db线程访问就行了。
  6. 后台工具。如统计、监控、日志归档、物理结构优化,每个任务,由调度器动态的启一个专门处理器。

现代操作系统的线程切换仍然比DB希望的还有重量级,但是多处理器下效率比古典操作系统有很多提升。历史上看,DB首先是多进程单线程的,后来随着OS多线程能力的提升DB将多进程改为多线程,这样的好处是编程方便。当代DB“ are written in this manner, and can be run over either processes or threads.”,把线程视为可调度单元。那么为什么还有现代DB还坚持着多进程的并发模型呢?当前的硬件,例如x86的Linux一个进程只能支持到3GB ram,多进程可以减轻这个问题。

例举几种数据库的并发模型

  Oracle DB2 SQL Server
Unix环境 Process-Per-User Process-Per-User 不支持
Window环境 以线程为调度单元 以线程为调度单元 thread-per-session,但是thread可复用

2.4 并发、进程模型、内存协调

  描述 pros cons
shared memory 由于OS通常支持可调度单元(线程或进程)在多处理器之间的透明调度,且共享内存可全部被读到 简便 硬件行业摇钱树
shared Nothing

由PC机(一般是刀片)组成;某CPU不能直接访问另一个CPU的内存或磁盘;由于便宜、扩展性好,这类机器常用于数据仓库;
硬件共享上没有抽象,因此要求DBMS能调度如此多的机器:除运行服务进程,还需要支持单个请求在多台机器上并行执行。
数据上,一般水平切割;查询调度器负责分派查询任务、传播数据,不需要动到每个机器的线程状态、或其他底层信息。
数据拆分并不能保证事务、负载均衡、维护任务(如死锁检测、两阶段提交),因此既要有额外逻辑保障以上功能,又不能让以上逻辑成为瓶颈。
无共享架构下节点故障三种情况:
1. 整个系统挂机
2. 若看中可用性强过一致性,允许查询宕机节点以外数据
3. 通过冗余如链式分解保证可用性。链式分解目前只实现了粗糙的方案,例如数据库复制。

便宜、扩展性好

贵,因为license按软件包收费,例如IBM SP2、NCR WorldMark机器;
按数据拆分,DBA运维压力大;

shared disk

single-box数据库,分布式部署在多台服务器上。随着NAS的流行,这种数据库也流行开来。
例如MemSQL,例如Oracle不支持sharednothing但是支持shared disk。

1. 比起shared nothing,DBA不需要考虑数据分片;
2. 比起shared memory,不用担心丢失调度单元
3.节点故障完全不影响其他节点;但是存储的可靠性非常重要。

数据的共享需要软件去协调:所有节点都能从磁盘拷贝到自己内存,都有自己的锁、buffer pool页。因此至少需要:
1. 分布式锁管理机制
2. cache-coherency缓存一致性协议来管理分布的buffer pool。
以上代码复杂,可能成为瓶颈。

NUMA

在NUMA架构中,每个Node有多个Core,Node内CPU与内存通过片内总线连接,Node间通过互联网模块进行连接。每个core地位是平等的,都可以访问所有内存,访问其它节点内存耗时用node-distance衡量,一般比访问本机慢3倍。IBM这类厂商提供NUMA架构的机器。
虽与shared-memory同为共享内存架构的并行机器,NUMA一般被看作比较贵的Shared-nothing架构机器:
1. 像shared-nothing一样轻巧的Node:Node一般是4通道CPU
2. DBMS通常忽略其共享内存的特性,这是因为本机/跨机内存访问速率不一致。

  所有数据库都被NUMA坑过,例如MySQL swap insanity,其原因基本上“CPU亲和策略导致内存分配不均”或者“NUMA Zone Clain内存回收”

2.5 准入控制

“如何支持并发的请求”。为什么说准入控制是必要的?因为当负载拆过临界点后,系统就会开始抖动,从OS层面看,抖动多数情况由DBMS的buffer pool不停换入换出导致的,DBMS在执行排序、hash join,或者锁竞争、事务死锁的情况下尤其消耗内存。 准入控制可以使服务优雅降级:事务延迟会随着请求速率慢慢降低,但系统吞吐量维持在峰值。
如何做DB准入控制?
1. 限流。要求dispatcher进程保障客户连接数载某个数字以内,这样既可以保证不过度消耗网络连接资源,也可以使查询解析器和查询优化器掉用量比较小。有些DB把这个功能甩锅给其它应用,如应用服务器、事务监视器TPM、Web服务器。
2. 执行准入控制器execution admission controller,需要再DBMS查询处理器内部实现。执行控制器用于决策一个查询要立即执行还是延迟执行,是在查询被解析、优化后调用的,因为它需要优化器产生的查询计划里的信息来估算资源,这些信息包括:

2.1 有哪些磁盘访问
2.2 每块设备的随机/次序IO的预期CPU负载
2.3 查询内存占用,尤其是排序和hash表 ***

2.3是execution admission controller最重要的决策信息,因为内存压力才是抖动的主要原因。

2.6 小结

1. 当代DBMS既有Process-per-User又有“Server process”模型。前者简单;后者可支持更高性能。
2. 有些DBMS自己实现了线程包(如Oracle、Informix),因此以线程为可调度单元。
3. 不同OS上可调度单元不同,有的OS以进程为可调度单元,有的OS以单进程内的线程为可调度单元。
并发架构上,市面上有Shared-Nothing、Shared-Memory和Shared-Disk的架构。其中,Shared-nothing善于高性价比的处理海量数据的复杂查询,因此在协作决策支持系统中占据高端地位;其它两种善于处理多个小事务。将单处理器DB应用到shared-nothing架构难度较高,很多数据库公司宁愿直接开发新产品线,如Oracle直接不支持Shared-Nothing架构。

Anatomy of a Database System学习笔记 - 概论、并发控制的更多相关文章

  1. Anatomy of a Database System学习笔记 - 查询

    查询解析 解析会生成一个查询的内部展示.格式检查包含在解析过程中. 每次解析一个SELECT,步骤如下:1. 从FROM里找到表名,转换成schema.tablename.这一步需要调用目录管理器ca ...

  2. Anatomy of a Database System学习笔记 - 公共模块、结语

    公共模块 1. 使用基于上下文的内存分配器进行内存分配 除了教材里常提到的buffer pool,数据库还会为其他任务分配大量内存,例如,Selinger-style查询优化需要动态的规划查询:has ...

  3. Anatomy of a Database System学习笔记 - 事务:并发控制与恢复

    这一章看起来是讲存储引擎的.作者抱怨数据库被黑为“monolithic”.不可拆分为可复用的组件:但是实际上除了事务存储引擎管理模块,其他模块入解析器.重写引擎.优化器.执行器.访问方式都是代码相对独 ...

  4. Anatomy of a Database System学习笔记 - 存储管理

    使用裸设备,还是使用文件系统?   描述 pros cons 裸设备 顺序读磁盘快比随机要快10-100倍,DB比OS更懂磁盘负载,因此很多DB是直接管理数据块如何存放的. DB对裸设备的管理,比文件 ...

  5. A.Kaw矩阵代数初步学习笔记 5. System of Equations

    “矩阵代数初步”(Introduction to MATRIX ALGEBRA)课程由Prof. A.K.Kaw(University of South Florida)设计并讲授. PDF格式学习笔 ...

  6. Deap Learning (吴恩达) 第一章深度学习概论 学习笔记

    Deap Learning(Ng) 学习笔记 author: 相忠良(Zhong-Liang Xiang) start from: Sep. 8st, 2017 1 深度学习概论 打字太麻烦了,索性在 ...

  7. system generator学习笔记【02】

    作者:桂. 时间:2018-05-20  23:28:04 链接:https://www.cnblogs.com/xingshansi/p/9059668.html 前言 继续学习sysgen.接触s ...

  8. System类学习笔记

    最近在学习源码的过程中发现:很多深层次的代码都用到了一个类System类,所以决定对System类一探究竟 本文先对System类进行了剖析,然后对System类做了总结 一.首先对该类的中的所有字段 ...

  9. 学习笔记之操作系统(Operating System)

    学习笔记之多线程 - 浩然119 - 博客园 https://www.cnblogs.com/pegasus923/p/5554565.html 用三个线程按顺序循环打印ABC三个字母 - 浩然119 ...

随机推荐

  1. 虚函数表:QT5与VS2015的差异

    问题原自下面一段代码: 初学C++虚函数表时,以下代码在QT和VS(版本如题)编译结果不同. #include <iostream> using namespace std; class ...

  2. MyBatis-Spring开发记录贴(新手)

    初学MyBatis-Spring,发个帖子记录一下自己的学习历程,先写个自己的编程步骤. 1.先进行数据库设计. 2.根据所设计的数据,写出相应的POJO,并写出setter和getter方法. 3. ...

  3. 搭建开发环境2)Debian8 安装jdk 1.8

    1.由于Debian自带了openjava运行时需要先卸载掉 java -version //查看当前java版本 apt-get remove openjdk* //卸载当前的openjdk 2.下 ...

  4. Git 几个常用操作

    git init        --    初始化仓库, git clone    --    从远端克隆仓库到本地 git status   --    查看git仓库的状态 git log    ...

  5. java的接口

    接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法. 接口并不是类,编写接口 ...

  6. java单例设计模式总结及举例

    * 设计模式:前人总结出来的经验,被后人直接拿来使用. * 单例设计模式:一个类只允许有一个对象,将这个对象作为一个全局的访问点,提供出去供大家使用. * 分析: * 1.用户只能有一个对象 * 2. ...

  7. scipy 的K-means

    #导入相应的包 import scipy import scipy.cluster.hierarchy as sch from scipy.cluster.vq import vq,kmeans,wh ...

  8. maven 项目pom文件引入lib下的jar包

    <dependency> <groupId>abc</groupId> <artifactId>abc</artifactId> <v ...

  9. pl/sql oracle数据库中文数据显示异常或者不能使用中文查询的解决办法

    1首先我们需要找到pl/sql developer 目录 然后在该目录下 创建一个bat文件 在文件中定义 set NLS_LANG=AMERICAN_AMERICA.UTF8start PLSQLD ...

  10. 纪念使用FTPClient工具所遇到的

    我所使用的是org.apache.commons.net.ftp.FTPClient.  查了资料还有其余几个FTPClient,其余的先不展开. 1.ftpClient.changeWorkingD ...