数据库基础

关系型数据库

指采用了关系模型来组织数据的数据库,关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。

  • 优点
    • 容易理解:二维表结构是非常贴近逻辑世界的一个概念,关系模型相对网状、层次等其他模型来说更容易理解;
    • 使用方便:通用的SQL语言使得操作关系型数据库非常方便;
    • 易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率。
  • 缺点
    • 高并发场景下,IO是个很大瓶颈;
    • 海量数据,读写效率低;

三范式

  • 第一范式(1NF)

    强调的是列的原子性,不可分割。例如一张学生表:

    年龄
    23
    24

    由于姓名是不可以分割的,因此违背了第一范式。

  • 第二范式(2NF)
    首先要符合第一范式,还需要符合两个条件:

    • 表必须要有主键;
    • 非主键的列必须完全依赖于主键。
学号 姓名 课程号 学分
N01 张三 C01 81
N01 张三 C02 82
N02 李四 C02 92

可以看到假设这张表 主键=学号+课程号,学分完全依赖于主键,但是姓名却不完全依赖于主键,姓名依赖于学号(主键的部分),所以违反了非主键的列必须完全依赖于主键。

  • 第三范式(3NF)
    在第二范式基础上进行了增强,不存在传递依赖

    学号 姓名 班级编号 班级名称
    N01 张三 001 一班
    N02 李四 002 二班

    由于【班级名称】依赖于【班级编号】,说明存在传递依赖。

第二范式与第三范式容易混淆,第二范式强调的是非主键必须完全依赖于主键,完全依赖指的是不能依赖于主键的部分属性;第三范式强调的是,满足了第二范式的情况,不能出现传递依赖,可以看到【班级名称】完全依赖于【学号】,但是【班级名称】却又依赖于【班级编号】。

SQL

结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。语言结构主要包含如下6部分:

  • 数据定义语言(DDL):创建、修改或删除表(create、alter、drop);为表加入索引等;
  • 数据操作语言(DML):对表数据进行添加、修改或删除(insert、update、delete);
  • 数据查询语言(DQL):用以从表中获得数据,保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。这些DQL保留字常与其它类型的SQL语句一起使用。
  • 事务控制语言(TCL):它的语句能确保被DML语句影响的表的所有行及时得以更新。包括COMMIT(提交)命令、SAVEPOINT(保存点)命令、ROLLBACK(回滚)命令。
  • 数据控制语言(DCL):它的语句通过GRANT或REVOKE实现权限控制,确定单个用户和用户组对数据库对象的访问。
  • 指针控制语言(CCL):它的语句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用于对一个或多个表单独行的操作。

事务

概念

数据库事务(transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

考虑这么一个场景:屌丝小明招行账户有100块钱,建行账户有0块钱,现在要从招行转账80块钱给自己建行账户。

  1. 招行执行 100 - 80 = 20逻辑;
  2. 建行执行0 + 80 = 80逻辑。

如果这两段逻辑,只要有一个失败,就必须全部撤回;否则成功提交。因此这两段逻辑合起来就是一个事务。

事务的四大特性ACID

  • 原子性(Atomicity): 事务是一个不可分割的单位,要么全部提交,要么全部回滚;
  • 一致性(Consistency):完成事务后,所有数据的状态都是一致的,从上面转账场景来说,无论怎么转账,小明招行 + 建行的总余额=100;
  • 隔离性(Isolation): 多个事务并发的执行,每个事务之间不能互相干扰,当然最终由隔离级别来确定。
  • 持久性(Durability):事务一旦被提交,对数据的改变就是永久的,即持久化到磁盘。

事务并发问题

  • 脏读(读了其他事务未提交的数据):指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据;


    image

    如上图所示:小明和小明他爸对同一个账户(假设初始余额=100)操作。

    • 小明先做了其他操作,与此同时他爸修改了余额=20,他爸并没有提交事务;
    • 小明接着查看余额=20,接着又做了其他操作,最后提交了事务

如果此时他爸事务回滚,说明他爸此次操作无效,小明取到的就是无效值,如果小明拿着这个无效值做了其他操作,可能会引发严重数据问题。

  • 不可重复读(多次读了其他事务已提交的某条数据,数据内容不一致):是指在一个事务(A)内,多次读同一条数据,如果在读取期间,其他的某个事务(B)修改了该数据并提交,那么就会导致事务A读取到事务B修改过的数据,造成多次读取数据不一致;


    image

    如上图所示:小明和小明他爸对同一个账户(假设初始余额=100)操作。

    • 小明先查看余额=100,与此同时他爸修改了余额=20,他爸提交了事务;
    • 小明接着做了其他操作,又查看余额=20,发现两次查询的余额不一样。

如果小明在其他操作的时候使用了余额=100,在其他操作做了某些计算,接着查询余额的却是20,相当于前面其他操作都白做了。

  • 幻读(多次读取,返回的记录数不同):所谓幻读,指的是当某个事务(A)在读取某个范围内的记录时,另外一个事务(B)又在该范围内插入了新的记录,事务A再次读取该范围的记录时,会产生幻行。


    image

    如上图所示:某个班级的学生表。

    • 事务A先查看身高=180的人数假设=3个,与此同时事务B添加身高=183的小东同学,事务B提交了事务;
    • 事务A接着做了其他操作,又查看身高=180的人数=4个,发现两次查询的行数不一样。

假设统计身高180的学生人数一开始=3,其他操作已经把人数记录了,接着查询身高180的学生人数却是4,相当于前面其他操作都白做了。

事务隔离级别

  • Read Uncommitted:读取未提交,某个事务读取另外事务修改且未提交的数据,是最低的隔离级别;

  • Read Committed:读取已提交,某个事务读取另外事务修改且已提交的数据;

  • Repeatable Read:可重复读,多次读了其他事务已提交的某条数据,数据都一样;

  • Serializable:串行化,读加共享锁,写加排他锁,读写互斥,并发能力非常差,是最高的隔离级别。

    隔离级别与并发问题 脏读 不可重复读 幻读
    Read Uncommitted
    Read Committed ×
    Repeatable Read × ×
    Serializable × × ×

数据库完整性约束

数据的完整性是指数据的正确性和一致性,可以通过定义表(索引,触发器等)时定义完整性约束。

约束 说明
NOT NULL(非空约束) 指定列不能存储NULL值
UNIQUE(唯一约束) 指定列的每行必须有唯一的值(NULL值除外)
PRIMARY KEY(主键约束) 指定列为主键
FOREIGN KEY(外键约束) 指定列为外键
CHECK(检查约束) 指定列的值要符合check条件
DEFAULT(默认值约束) 指定列设置默认值

你可能感兴趣的:(数据库基础)