数据库的基本要求

  • 原子性。

    • 影子拷贝:写操作执行在数据库的副本上,而原始数据库保持不变。若某操作需要中止,只需要删除副本。

  • 一致性。

    • 完整性约束检查。

  • 隔离性。

    • 两阶段锁:能够保证事务的可串行化执行,可能发生死锁。

  • 持久性。

关系数据库的基本概念

关系的基本术语:

  • 属性(Attribute):在现实世界中,要描述一个事物常常取若干特征来表示。这些特征称为属性。例如学生通过学号、姓名、性别、系别、年龄、籍贯等属性来描述。

  • 域(Domain):每个属性的取值范围对应一个值的集合,称为该属性的域。

    例如,学号的域是 6 位整型数,姓名的域是 10 位字符;性别的域为{男,女}等。一般在关系数据模型中,对域还加了一个限制,即所有的域都应是原子数据(AtomicData)。例如,整数、字符串是原子数据,而集合、记录、数组是非原子数据。关系数据模型的这种限制称为第一范式(FirstNormalForm,1NF)条件。但也有些关系数据模型突破了 1NF 的限制。

  • 目或度(Degree):目或度指的是一个关系中属性的个数。

  • 候选码(CandidateKey):若关系中的某一属性或属性组的值能唯一的标识一个元组,则称该属性或属性组为候选码。

  • 主码(PrimaryKey):或称主键,若一个关系有多个候选码,则选定其中一个作为主码。

  • 主属性(PrimeAttribute):包含在任何候选码中的属性称为主属性。不包含在任何候选码中的属性称为非主属性(Non-PrimeAttribute)。

  • 外码(ForeignKey):如果关系模式 R 中的属性或属性组不是该关系的码,但它是其他关系的码,那么该属性集对关系模式 R 而言是外码。

    例如,客户与贷款之间的借贷联系 c-1(c-id,loan-no),属性 c-id 是客户关系中的码,所以 c-id 是外码;属性 loan-no 是贷款关系中的码,所以 loan-no 也是外码。

  • 全码(All-key):关系模型的所有属性组是这个关系模式的候选码,称为全码。

    例如,关系模式 \(R(T, C, S)\),属性 T 表示教师,属性 C 表示课程,属性 S 表示学生。假设一个教师可以讲授多门课程,某门课程可以由多个教师讲授,学生可以听不同教师讲授的不同课程,那么,要想区分关系中的每一个元组,这个关系模式 R 的码应为全属性 T、C 和 S,即 ALL-KEY。

  • 笛卡尔积。

关系数据库模式

关系的描述称为关系模式(RelationSchema)。可以形式化地表示为:

\$R(U, D, dom, F)\$

其中: - \$R\$ 表示关系名。 - \$U\$ 是组成该关系的属性名集合是属性的域。 - \$dom\$ 是属性向域的映像集合。 - \$F\$ 为属性间数据的依赖关系集合。

通常将关系模式简记为:

\$R(U) 或 R(A_1, A_2, A_3, \cdots, A_n)\$

为关系名,\(R\) 为关系名,\(A_1, A_2, A_3, \cdots , A_n\) 为属性名或域名,属性向域的映像常常直接说明属性的类型、长度。通常在关系模式主属性下加下划线表示该属性为主码属性。

可以简单将关系模式当作表的字段元组。

函数依赖

给定关系模式 \(R(U, F)\),其中属性集 \(U={A_1, A_2, A_3, A_4, A_5, A_6}\)、函数依赖集 \(F={A_1->A_2, A_1->A_3, A_3->A_4, A_1A_5->A_6}\)。则可以确定:

  • 由于 \(A_1A_5\) 仅出现在函数依赖集的左部。因此 \(A_1A_5\) 为 \(R\) 的主码。

  • 由于 \(A_1A_5\) 的闭包为 \(U\),因此 \(A_1A_5\) 为 \(R\) 的唯一候选码。

数据库设计

数据库设计阶段分为以下阶段:

  • 需求分析阶段:形成需求说明文档、数据字典和数据流图。

  • 概念结构设计。

  • 逻辑结构设计。

    • 进行关系规范化。

  • 物理结构设计。

基本概念

数据模型描述的内容包括三个部分:数据结构、数据操作和数据约束

乐观锁和悲观锁

  • 乐观锁:乐观锁在操作数据时认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据,如果别人修改了数据则放弃操作,否则执行操作。

  • 悲观锁:悲观锁在操作数据时认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。

CAS 的参数一共有三个,第一个是内存地址,第二是期望值,第三个是新值。如果内存处的值与期望值相等就进行更新,否则退出。CAS 的操作是原子性的。一般将 CAS 配合 yield + while 对内存进行更新

原子变量就是乐观锁

乐观锁适用于单个变量,悲观锁适用于多个变量

乐观锁在竞争不激烈时具有优势,悲观锁在竞争激烈时更有优势。因为乐观锁中存在忙等

乐观锁本身不加锁,但是可以和悲观锁相配合

CAS 的缺点:

  • ABA问题

    假设有两个线程——线程1和线程2,两个线程按照顺序进行以下操作:

    1. 线程1读取内存中数据为A;

    2. 线程2将该数据修改为B;

    3. 线程2将该数据修改为A;

    4. 线程1对数据进行CAS操作

    在第(4)步中,由于内存中数据仍然为A,因此CAS操作成功,但实际上该数据已经被线程2修改过了。这就是ABA问题。

    在AtomicInteger的例子中,ABA似乎没有什么危害。但是在某些场景下,ABA却会带来隐患,例如栈顶问题:一个栈的栈顶经过两次(或多次)变化又恢复了原值,但是栈可能已发生了变化。

    对于ABA问题,比较有效的方案是引入版本号,内存中的值每发生一次变化,版本号都+1;在进行CAS操作时,不仅比较内存中的值,也会比较版本号,只有当二者都没有变化时,CAS才能执行成功。Java中的AtomicStampedReference类便是使用版本号来解决ABA问题的。

  • 高竞争下的开销问题

    在并发冲突概率大的高竞争环境下,如果CAS一直失败,会一直重试,CPU开销较大。针对这个问题的一个思路是引入退出机制,如重试次数超过一定阈值后失败退出。当然,更重要的是避免在高竞争环境下使用乐观锁。

  • 功能限制

    CAS的功能是比较受限的,例如CAS只能保证单个变量(或者说单个内存值)操作的原子性,这意味着:(1)原子性不一定能保证线程安全,例如在Java中需要与volatile配合来保证线程安全;(2)当涉及到多个变量(内存值)时,CAS也无能为力。

    除此之外,CAS的实现需要硬件层面处理器的支持,在Java中普通用户无法直接使用,只能借助atomic包下的原子类使用,灵活性受到限制。

  • 面试官:你了解乐观锁和悲观锁吗?

MySQL 中的锁

存储引擎

行锁

表锁

页锁

MyISAM

\(\checkmark\)

BDB

\(\checkmark\)

\(\checkmark\)

InnoDB

\(\checkmark\)

\(\checkmark\)

  • 行锁是存储引擎实现的作用在索引上的。如果在建表的时候没有定义一个索引,InnoDB 会创建一个聚簇索引并将其作为锁作用的索引

  • 表锁是由 MySQL Server 实现的。因此所有的引擎都支持

两种锁的比较

表锁:加锁过程的开销小,加锁的速度快;不会出现死锁的情况;锁定的粒度大,发生锁冲突的几率大,并发度低;

  • 一般在执行DDL语句时会对整个表进行加锁,比如说 ALTER TABLE 等操作;

  • 如果对InnoDB的表使用行锁,被锁定字段不是主键,也没有针对它建立索引的话,那么将会锁整张表;

  • 表级锁更适合于以查询为主,并发用户少,只有少量按索引条件更新数据的应用,如Web 应用。

行锁:加锁过程的开销大,加锁的速度慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;

  • 最大程度的支持并发,同时也带来了最大的锁开销。

  • 在 InnoDB 中,除单个 SQL 组成的事务外,锁是逐步获得的,这就决定了在 InnoDB 中发生死锁是可能的。

  • 行级锁只在存储引擎层实现,而 MySQL 服务器层没有实现。 行级锁更适合于有大量按索引条件并发更新少量不同数据,又有并发查询的应用,如一些在线事务处理(OLTP)系统。

事务

事务的特征 ACID

分别代指原子性、一致性、隔离性、持久性

数据安全

数据的安全和一致性主要是由于并发引起的,这儿包括脏读、幻读、不可重复读

  • 脏读:事务 A 在更新数据的时候事务 B 读取了数据。但是这时数据还没有更新为正确的值(比如事务失败回滚),事务 B 就发生了脏读。也就是说事务 B 读到了事务 A 未提交的数据

  • 幻读:事务 A 和事务 B 同时对数据进行更新,导致事务 A 更新的数据被事务 B 覆盖

  • 不可重复读:事务 A 两次读取到的数据不一样

级别高低:脏读 < 不可重复读 < 幻读

所以设置了最高级别的SERIALIZABLE_READ就不需要设置其他的了,即解决了幻读问题那么脏度和不可重复读自然就都解决了。

数据库的隔离级别为:

隔离级别作用

Read Uncommitted

什么也不做

Read Committed

事务提交后才能读取数据,解决幻读

Repeated Read

在一个事务中,对同一份数据的读取结果总是相同的,解决脏读、解决重复读

Serialization

事务串行执行。通过牺牲系统的并发性解决并发事务的所有问题

排它锁和共享锁

  • 排它锁 (eXclusive Lock) 又称为写锁、X 锁。在事务对数据加锁期间可以进行读写,但是不允许其他事务加锁

  • 共享锁 (Shared Lock) 又称为读锁、S 锁。在事务加锁期间允许读,不允许写。加锁期间允许其它事务加共享锁,但是不允许加写排它锁

数据库安全保护

DBMS对数据库的安全保护方功能是通过四方面实现的,即安全性控制、完整性控制、并发性控制和数据库恢复:

  • 安全性控制:使用用户标识和鉴定、用户存取权限控制、定义视图、数据加密和审计等防止用户绕过 DBMS 直接通过操作系统访问

  • 完整性控制:

  • 并发性控制:

  • 数据库恢复:

  • 数据库安全保护

  • 数据库的保护

连接

分为内连接(等值连接)和外连接

内连接是 INNER JOIN 。左右表取交集 外连接包含了左连接和右连接。 LEFT JOIN 和 RIGHT JOIN

数据库三级模式结构

数据库系统的三级模式结构是指模式、外模式和内模式

  • 模式:逻辑模式或者概念模式。是所有用户的公共数据视图。位于三级结构的中间

  • 外模式:也叫用户模式。是数据库用户能看到的数据视图。外模式是模式的子集,一个模式可以有多个外模式

  • 内模式:一个数据库只有一个内模式。内模式是数据库内部数据的表示方式。

三级模式保证了数据的独立性

索引

索引的好处:[1]

  • 数据库索引能避免进行数据库全表的扫描。

  • 特定的情况下,索引可以避免排序操作。

  • 存在非聚集索引时,有时无需访问数据页即可得到数据。

  • 存在聚集索引时,有时无需访问数据页即可得到数据。

建立索引不一定提高查询速度,这取决于索引是否有助于查询。例如对于需要全表扫描的查询而言,有没有索引没什么影响

数据库范式

一共是六个范式,1NF→2NF→3NF→BCNF→4NF→5NF

其中:

  • 1NF:数据表中的所有码都是不可再分的

  • 2NF:存在唯一一个主键,且其它关键字与主键一一对应

  • 3NF:非主属性不依赖于非主键属性 BCNF:

  • 4NF:当一个表中的非主属性相互独立时,这些非主属性不应该有多值

  • 5NF:表必须可以分解为较小的表,除非那些表在逻辑上拥有与原始表相同的主键。

主键

根据 2NF 。主键不可为空,主键必须能够代表当前元组的信息

主键可为联合主键

但是对于存在唯一索引的非主键而言,允许一个为空

数据库安全

措施说明

用户标识和鉴定

最外层的安全保护措施,可以使用用户帐户、口令及随机数检验等方式。

存取控制

对用户进行授权,包括操作类型(如查找、插入、删除、修改 等动作)和数据对象(主要是数据范围)的权限。

密码存储和传输

对远程终端信息用密码传输

视图的保护

对视图进行授权

审计

使用一个专用文件或数据库,自动将用户对数据库的所有操作记录下来。

数据备份

从数据库系统的运行状态来看,可以将备份方式分为冷备份和热备份:

备份方式优点缺点

冷备份

在系统停机的状态下进行备份。

  • 简单

  • 没有数据不一致的风险。

  • 备份慢

  • 系统需要停机

热备份

在系统不停机的状态下进行备份。

  • 无需停机

  • 复杂

  • 需要确保数据一致性问题。

从数据的备份方式上而言,可以分为完全备份、差量备份和增量备份:

备份方式

完全备份

备份所有数据。

差量备份

仅备份上一次 完全备份 之后变化的数据。

增量备份

备份 上一次备份 之后变化的数据

NoSql

NoSql(Not-only SQL) 是非关系型数据库。常见的 NoSql 数据库有键值数据库和文档数据库。

关系数据库的缺陷:高并发读写的性能低、支撑容量有限、数据库的可扩展性和可用性低、建设和运维成本高。

关系数据库模式NoSQL模式

并发支持

支持并发、效率低

并发性能高

存储与查询

关系表方式存储、SQL查询

海量数据存储、查询效率高

扩展方式

向上扩展

向外扩展

索引方式

B树、哈希等

键值索引

应用领域

面向通用领域

分布式数据库

传统集中式数据库两阶段提交协议为:加锁阶段和解锁阶段,也被成为拓展阶段和收缩阶段。

分布式数据库两阶段提交协议中的两个阶段为 表决阶段执行阶段

透明性

  • 分片透明:用于无需了解逻辑上访问的表是如何分块存储的。

  • 复制透明:用于无需知道数据是复制到哪些节点。

  • 位置透明:用户无需了解数据存放的物理位置。

  • 逻辑透明(局部数据模型透明):用户无需了解局部场地使用的是哪种数据模型。

数据挖掘

数据挖掘的主要任务有:聚类分析、分类分析和关联规则挖掘等。

故障处理

当系统发生故障时,对于事务:

  • 已经开始,但是没有提交:什么都不做。

Last moify: 2024-10-08 02:26:47
Build time:2025-07-18 09:41:42
Powered By asphinx