

数据库是如何获取并处理数据的
source link: https://www.51cto.com/article/716515.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

数据库是如何获取并处理数据的-51CTO.COM
SQL是结构化查询语言(Structured Query Language)的简称,用户只需要通过SQL告诉数据库需要什么,至于怎么去做就是数据库管理系统(DBMS)需要考虑的问题。
SQL是结构化查询语言(Structured Query Language)的简称,用户只需要通过SQL告诉数据库需要什么,至于怎么去做就是数据库管理系统(DBMS)需要考虑的问题。

上篇文章《SQL语句处理》介绍了数据库执行的四个阶段,每个阶段都做了什么工作。今天这篇文章继续探讨数据库是如何获取到用户所需的数据。
如下所探讨的内容仅适用于Oracle单机环境,RAC环境稍有不同,不在本篇讨论范围内。
数据库的所有操作增、删、改、查都是在内存中完成的,为了处理数据,数据库首先需要将数据从磁盘读取到内存中,然后进行相应的操作。但是内存和磁盘的读写速度有着天壤之别。DDR4内存读写速度大概50G每秒(50000M),固态硬盘速度是300M每秒,是内存的二百分之一,机械硬盘的速度是100M每秒,是内存的五百分之一。为了解决两者之间的速度差的问题,诞生了缓存的概念。缓存的作用就是避免每次获取数据时都从缓慢的磁盘读取,而是将之前访问过的数据缓存在内存中,后续操作如果需要相同数据时,直接从内存获取,大大提升读取速度。
Oracle内存结构中有一个很重要的结构叫做DB Buffer Cache,DB Buffer Cache位于SGA中,正常系统中此部分内存占整个Oracle内存结构大绝大部分。如果DB Buffer Cache很大,几十G,甚至是几百G,每次在其中搜索所需的块是否存在,也需要很长的时间,因此,为了提高效率,Oracle将DB Buffer Cache划分为多个区域,每个区域称为一个工作集(workset),每个工作集又被划分为多个hash buckets,一个hash buckets管理着一个或多个数据块。为了保证数据的一致性,hash buckets访问是串行的,由相应的latch保护,只有获取到相应的latch的会话才能到hash buckets上搜索数据块。

1、查询语句的执行
假设有如下查询语句:
SELECT * FROM employees WHERE employee_id=199;
表employees表结构如下,employee_id是表的主键。

先看下上述sql语句的执行计划

首先根据索引EMP_EMP_ID_PK查找employee_id=199键,获取到键所对应的值ROWID,ROWID指向数据块的真实地址。通过ROWID获取数据块,获取到数据块后,再从数据块中获取符合条件的数据。在此过程中至少需要访问两个数据块(为了简化过程,忽略其他数据块),一个是键为199索引块,假设为100号块;另一个是索引块所指向的数据块,假设为1000号块。
前面缓存介绍中提到,为了提升数据的访问速度,Oracle会将访问过的数据块缓存到DB Buffer cache中,以备重复使用。因此上面获取100号索引块的时候,需要先到DB Buffer cache中查找100号索引块是否已存在,以减少昂贵的磁盘读。在搜索DB Buffer cache前,必须获取相应的latch后才能进行搜索。如果未获取到latch,此时会进入等待。待获取到latch后便可以对DB Buffer cache搜索。
如果100号索引块已存在于内存中,且没有会话正在修改数据块内容,直接访问内存中的数据块,获取键为199的数据。如果有会话正在修改此数据块内容,则需要通过undo数据和当前的数据块构造一个一致性读版本的数据块,来读取会话修改前的历史版本数据。
如果100号索引块不在内存中,首先判断是否有其他会话正在将100号索引块读入内存,如果是,则等待。否则通知后台进程将100号索引块从磁盘读入内存,在将100号索引块读入内存前,需要在内存中找到一块合适的空闲块,以便保存即将读入的100号索引块。搜索空闲块时同样需要获得latch。
如果内存中没有空闲的空间,则通知后台刷新进程刷新脏页,以腾出空闲空间。
如果内存中有空闲的空间,直接将100号索引块读入内存。获取到ROWID后,再去读取数据块,读取数据块的过程同读取索引块,读取到数据块后再从数据块中获取符合条件的行,返回给客户端。

2、DML语句执行
假设有如下更新语句:
UPDATE employees SET first_name='Hello',last_name='Kitty' WHERE employee_id=199;
update语句执行计划如下:

DML语句都存在相应的查询过程,因为只有查询到了所需要修改的数据,才能进行相应的操作。查询的过程大致与查询语句执行过程相同。但也有如下不同点:
获取latch时,如果是只读操作,多个会话可以同时获取相同的latch,如果是DML操作,则不可以同时获得。
只读操作多个会话可以同时读取同一个数据块,DML操作则不可以多个会话同时修改同一个数据块。
获取到数据块后进行相应的操作,并记录对应的undo信息和redo log信息,完成update操作。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK