数据库的基本要求
原子性。
影子拷贝:写操作执行在数据库的副本上,而原始数据库保持不变。若某操作需要中止,只需要删除副本。
一致性。
完整性约束检查。
隔离性。
两阶段锁:能够保证事务的可串行化执行,可能发生死锁。
持久性。
关系数据库的基本概念
关系的基本术语:
属性(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\$ 是组成该关系的属性名集合是属性的域。 - \$dom\$ 是属性向域的映像集合。 - \$F\$ 为属性间数据的依赖关系集合。
通常将关系模式简记为:
为关系名,\(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读取内存中数据为A;
线程2将该数据修改为B;
线程2将该数据修改为A;
线程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 实现的。因此所有的引擎都支持
两种锁的比较
表锁:加锁过程的开销小,加锁的速度快;不会出现死锁的情况;锁定的粒度大,发生锁冲突的几率大,并发度低;
|
行锁:加锁过程的开销大,加锁的速度慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
|
事务
事务的特征 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 锁。在事务加锁期间允许读,不允许写。加锁期间允许其它事务加共享锁,但是不允许加写排它锁
数据库安全保护
连接
分为内连接(等值连接)和外连接
内连接是 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树、哈希等 | 键值索引 |
应用领域 | 面向通用领域 |
分布式数据库
传统集中式数据库两阶段提交协议为:加锁阶段和解锁阶段,也被成为拓展阶段和收缩阶段。
分布式数据库两阶段提交协议中的两个阶段为 表决阶段 和 执行阶段。
透明性
分片透明:用于无需了解逻辑上访问的表是如何分块存储的。
复制透明:用于无需知道数据是复制到哪些节点。
位置透明:用户无需了解数据存放的物理位置。
逻辑透明(局部数据模型透明):用户无需了解局部场地使用的是哪种数据模型。
数据挖掘
数据挖掘的主要任务有:聚类分析、分类分析和关联规则挖掘等。
故障处理
当系统发生故障时,对于事务:
已经开始,但是没有提交:什么都不做。