说明:本文为openGauss技术文章征集作品参赛之一。
学习笔记:OpenGauss之SQL概念
1.介绍就简单的记录下SQL的一些基本概念,就像mysql、SQL Server、oracle等数据库都各自有自己的语言,尽管大致上基本一致,有些语法在细微上略有不同。openGauss也必然会如此。(推荐入门书:《数据库系统概念》、《SQL必知必会》、《openGauss数据库核心技术》)2.SQL之事务2.1 什么是事务?
一般概念性的东西都比较抽象,理解起来不容易懂。事务的基本概念就是“用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是不可分割的单位”。
这一听有点难理解什么叫做不可分割呢?举个转账的例子2.1,如下:
账户A有200元,账户B有300元,同学C某天从账户A转出100元到账户B,那么实际情况应该是A账户减100元,B账户加100元。但是这实际上是两个步骤,步骤一:A-100=100;步骤二:B+100=400。那么这两个步骤是算一个事务呢还是两个事务呢?答案是两个,要是是两个事务,那就完蛋了,银行执行完事务1以后不执行事务2,那同学C不就要告他了。所以这两个步骤是一个事务,且不能分割的,执行了步骤一就必须执行步骤二。2.2 事务的一些基本特性
事务的四大特性:ACID。A指的是原子性,B指的是一致性,C指的是隔离性,D指的是持久性。有没有感觉说了和没说一样,概念性东西就是这么难理解。
A(原子性):就是和原子一样不可再分。可见例子2.1。
B(一致性):保证事务只能把数据库从一个有效(正确)的状态“转移”到另一个有效(正确)的状态。那么什么是有效的状态呢?其实可以理解为一种数据约束,就是我们规定了默写数据存在的默认值或者说是默认限度。例如银行转钱,你卡里只有20块,所以你不可能转出大于20的金额,只能是小于20的金额,这就是一致性的体现。转钱的初始有效状态是20元,然后转出必须要满足另外一个有效状态即20-X>=0(X为转钱金额) 。
C(隔离性):就是事务之间不能相互干扰。就是事务A与事务B的操作在并发时,是不能相互影响的。隔离性可以解决一下三个问题:脏读、不可重复读、幻读。
脏读:事务A修改了一个数据,但是没有commit,事务B读到了这个修改了但是没有被提交的数据这就是脏读。
不可重读读:一个事务中对同一个数据读取的结果不一样。
幻读:一个事务中多次查询结果不一致。
脏读是在多个事务之间发生的,不可重复读和幻读是在一个事务中发生,且两个一个是读数据一个是查数据都是结果不一致导致。
D(持久性):事务提交以后,对系统的影响是持久的。就是事务一旦commit之后,不能在进行rollback。但是没有提交之前,对事务的修改都是可以通过rollback进行回滚到最初的状态。
以提交事务的语法为例:{COMMIT| END }[WORK | TRANSACTION]。注意[]内的内容是可选的。这里注意一点就是,如果是在事务中进行增删改查这些操作,只要没有commit都可以使用rollback进行回滚,回到上一步的状态下。2.3 事务的隔离级别
为什么要设置隔离级别?
因为如果不设置可能会导致脏读、不可重复读、幻读等问题(可见《SQL必知必会》)。
Read Uncommitted:最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。所有的并发事务问题都会发生。
Read Committed:只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。
Repeated Read:在一个事务中,对于同一份数据的读取结果总是相同的,无论是否
有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。
Serialization:事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。
隔离级别从上到下,逐渐增大。隔离级别若为序列化(Serializable),可以解决所有事务可能出现的问题。因为这个序列化级别并不是并行的,而是串行的,简单点说有种先来先服务算法的感觉在里面,它是一种按照顺序来执行事务的操作,所以无法同时执行多个事务。所以这也必然导致某些资源的浪费并且降低并发性。好处就是它能杜绝事务可能的问题,毕竟事务是按照顺序一个一个执行。
所以openGauss支持几个隔离级别呢?openGauss实际支持的事务隔离级别有两个:Read Committed(读提交)、Repeateble Read(重复读)。
事务隔离级别设置语法:set transaction isolation level repeatable read;(repeatable read 你可以换成其他的级别也一样)。(这里可能在设置事务级别会出现一个问题:SET TRANSACTION ISOLATION LEVEL must be called before any query。这个时候只需要再一次开启这个事务,重新执行下语句,就是执行第二次操作)。2.4事务快照
这里提醒下设置事务中的快照,语法为:SET TRANSACTION SNAPSHOT snapshot_id; 这个事务的隔离级别必须是repeatable read。设置事务的隔离级别必须在执行SQL语句之前。
设置完快照以后,快照怎么查?select pg_export_snashot();你查完以后它会返回一个快照id,这个id就可以代替snapshot_id了,这里提醒下,这个返回的id是字符串,所以记得打单引号引起来。3 SQL引擎3.1 SQL执行流程
大致分为四个部分:SQL解析、查询优化、查询执行、存储引擎。3.2 SQL解析
分为三个方面:词法、语法、语义。
(1) 词法分析:就是分析sql语句中的某些词,确定它的具体含义,如:select、+等。
(2) 语法分析:有点类似于英语中的语法规则的样子,sql语句也有一定的语法规则,语法分析就是判断sql是否符合sql语法规则,会生成对应的语法树。
(3) 语义分析:这个不同于词法分析,语义分析它是将语法分析中得到的语法书进行解析,检查的不再是关键词、运算符之类的,它检查的是列名、表名、函数名等数据。3.3 查询优化
通过查询优化器提高sql执行性能。那为什么需要查询优化器呢?原因是因为比起人工优化查询优化器计算力更强大速度更快。
SQL执行流程中openGauss数据库优化器默认使用的优化器就是基于代价的优化器,即CBO。CBO就是对执行路径进行代价估算,选择代价最低的执行路径(有点类似算法中的查找最短路径的算法的思想)。3.4 SQL执行引擎
其逻辑控制主要是围绕着关系运算来实现的,包含以下几个算子:扫描算子、控制算子、物化算子、连接算子。(详情可见《openGauss数据库核心技术》第八章)3.5 存储引擎
主要有是事务管理器(管理事务)、锁管理器(进行加锁解锁,解决事务并发的特性)、Heap(openGauss默认为堆表)、缓存区管理器(用于数据缓冲)、存储管理器(对数据进行行、列存储)、文件管理器(存储存储管理器中的数据)、磁盘(将文件管理器的内容刷入到磁盘中)、日志管理器(对数据进行持久化操作)、Redo日志文件(相当于将日志管理器中的内容备份,然后存入,再刷入磁盘中,刷入磁盘是为了放置当数据库宕机的时,可以将redo中内容重新写入磁盘)、Catalog数据字典(记录了数据库中的一些基本数据,如具有多少表)
openGauss中对于读、写事务的并发控制基于MVCC和快照机制(这两个机制在OceanBase中也用于解决并发问题,OceanBase是阿里的数据库),彼此之间不会存在事务级的长时间阻塞,可以实现读写不相互阻塞。
4.openGauss SQL语言基础
1. SQL 语言
DDL(create、drop、alter)、DML(insert、delete、update)、DQL(select)、DCL(grant、revoke)2. 基础(详细语法可见sql必知必会)
(1)select 语句基本功能。
(2)NULL 是不占用存储空间的。
(3)伪列(rownum、currval、nextval)
(4)逻辑操作符:AND 、OR、NOT。有三个值TRUE、FALSE、NULL。优先级 NOT>AND>OR。注意这些可以在一个SQL语句中一起使用或者同时使用多个,千万不要认为在一个sql中只能使用一种或者一个。
(5)比较操作符:between X and Y、not between X and Y、is。注意between and中的X和Y是必须要有顺序的,就是如果X、Y都为整形数据,且X的数值必须要小于Y才行,否则会报错。is是一个比较运算符,比较适合用来判断某些特殊值,例如是否为空值。
(6)别名:AS(可省略)。注意别名是可以用在表名和列名之后的。而且当别名中有特殊字符或者别名需要区分大小写时,要用双引号。
(7)消除重复行查询:distinct(直接消重)、group by(间接消重)。注意事项:关键字distinct前不能查询其他列(就是distinct关键字前面不能有其他列名的存在),而且一个select中只能有一个distinct。
(8)DML语法:insert、delete、update。这里提醒下delete、update时一定要加约束条件(就是where id=xx之类的),你要是不加这个限定条件,数据库可不知道你要删除或者更新那一条数据,它就会认为全部要更新,所以要是你不是全部要更新。
(9)这里openGauss在左/右外连接的语法做出一个一定的简化,比以前的SQL语法好理解一点。
![4c1e37782bd6abd7bbe01285e471752a.png](https://i-blog.csdnimg.cn/blog_migrate/f160e933298ad3fefb65388e38c9a719.jpeg)