对象类型 |
对象 |
操作类型 |
数据库模式 |
模式 |
CREATE SCHEMA |
基本表 |
CREATE SCHEMA ,ALTER TABLE |
视图 |
CREATE VIEW |
索引 |
CREATE INDEX |
数据 |
基本表和视图 |
SELECT ,INSERT ,UPDATE ,DELETE ,REFERENCES ,ALL PRIVILEGES |
属性列 |
SELECT ,INSERT ,UPDATE ,REFERENCES ,ALL PRIVILEGES |
> SQL 语法教程:[runoob . SQL 教程](http://www.runoob.com/sql/sql-tutorial.html)
### 关系型数据库
* 基本关系操作:查询(选择、投影、连接(等值连接、自然连接、外连接(左外连接、右外连接))、除、并、差、交、笛卡尔积等)、插入、删除、修改
* 关系模型中的三类完整性约束:实体完整性、参照完整性、用户定义的完整性
#### 索引
* 数据库索引:顺序索引、B+ 树索引、hash 索引
* [MySQL 索引背后的数据结构及算法原理](http://blog.codinglabs.org/articles/theory-of-mysql-index.html)
### 数据库完整性
* 数据库的完整性是指数据的正确性和相容性。
* 完整性:为了防止数据库中存在不符合语义(不正确)的数据。
* 安全性:为了保护数据库防止恶意破坏和非法存取。
* 触发器:是用户定义在关系表中的一类由事件驱动的特殊过程。
### 关系数据理论
* 数据依赖是一个关系内部属性与属性之间的一种约束关系,是通过属性间值的相等与否体现出来的数据间相关联系。
* 最重要的数据依赖:函数依赖、多值依赖。
#### 范式
* 第一范式(1NF):属性(字段)是最小单位不可再分。
* 第二范式(2NF):满足 1NF,每个非主属性完全依赖于主键(消除 1NF 非主属性对码的部分函数依赖)。
* 第三范式(3NF):满足 2NF,任何非主属性不依赖于其他非主属性(消除 2NF 主属性对码的传递函数依赖)。
* 鲍依斯-科得范式(BCNF):满足 3NF,任何非主属性不能对主键子集依赖(消除 3NF 主属性对码的部分和传递函数依赖)。
* 第四范式(4NF):满足 3NF,属性之间不能有非平凡且非函数依赖的多值依赖(消除 3NF 非平凡且非函数依赖的多值依赖)。
### 数据库恢复
* 事务:是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。
* 事物的 ACID 特性:原子性、一致性、隔离性、持续性。
* 恢复的实现技术:建立冗余数据 -> 利用冗余数据实施数据库恢复。
* 建立冗余数据常用技术:数据转储(动态海量转储、动态增量转储、静态海量转储、静态增量转储)、登记日志文件。
### 并发控制
* 事务是并发控制的基本单位。
* 并发操作带来的数据不一致性包括:丢失修改、不可重复读、读 “脏” 数据。
* 并发控制主要技术:封锁、时间戳、乐观控制法、多版本并发控制等。
* 基本封锁类型:排他锁(X 锁 / 写锁)、共享锁(S 锁 / 读锁)。
* 活锁死锁:
* 活锁:事务永远处于等待状态,可通过先来先服务的策略避免。
* 死锁:事物永远不能结束
* 预防:一次封锁法、顺序封锁法;
* 诊断:超时法、等待图法;
* 解除:撤销处理死锁代价最小的事务,并释放此事务的所有的锁,使其他事务得以继续运行下去。
* 可串行化调度:多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些事务时的结果相同。可串行性时并发事务正确调度的准则。
## 📏 设计模式
> 各大设计模式例子参考:[CSDN专栏 . C++ 设计模式](https://blog.csdn.net/column/details/15392.html) 系列博文
[设计模式工程目录](DesignPattern)
### 单例模式
[单例模式例子](DesignPattern/SingletonPattern)
### 抽象工厂模式
[抽象工厂模式例子](DesignPattern/AbstractFactoryPattern)
### 适配器模式
[适配器模式例子](DesignPattern/AdapterPattern)
### 桥接模式
[桥接模式例子](DesignPattern/BridgePattern)
### 观察者模式
[观察者模式例子](DesignPattern/ObserverPattern)
### 设计模式的六大原则
* 单一职责原则(SRP,Single Responsibility Principle)
* 里氏替换原则(LSP,Liskov Substitution Principle)
* 依赖倒置原则(DIP,Dependence Inversion Principle)
* 接口隔离原则(ISP,Interface Segregation Principle)
* 迪米特法则(LoD,Law of Demeter)
* 开放封闭原则(OCP,Open Close Principle)
## ⚙️ 链接装载库
> 本节部分知识点来自《程序员的自我修养——链接装载库》
### 内存、栈、堆
一般应用程序内存空间有如下区域:
* 栈:由操作系统自动分配释放,存放函数的参数值、局部变量等的值,用于维护函数调用的上下文
* 堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统回收,用来容纳应用程序动态分配的内存区域
* 可执行文件映像:存储着可执行文件在内存中的映像,由装载器装载是将可执行文件的内存读取或映射到这里
* 保留区:保留区并不是一个单一的内存区域,而是对内存中受到保护而禁止访问的内存区域的总称,如通常 C 语言讲无效指针赋值为 0(NULL),因此 0 地址正常情况下不可能有效的访问数据
#### 栈
栈保存了一个函数调用所需要的维护信息,常被称为堆栈帧(Stack Frame)或活动记录(Activate Record),一般包含以下几方面:
* 函数的返回地址和参数
* 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量
* 保存上下文:包括函数调用前后需要保持不变的寄存器
#### 堆
堆分配算法:
* 空闲链表(Free List)
* 位图(Bitmap)
* 对象池
#### “段错误(segment fault)” 或 “非法操作,该内存地址不能 read/write”
典型的非法指针解引用造成的错误。当指针指向一个不允许读写的内存地址,而程序却试图利用指针来读或写该地址时,会出现这个错误。
普遍原因:
* 将指针初始化为 NULL,之后没有给它一个合理的值就开始使用指针
* 没用初始化栈中的指针,指针的值一般会是随机数,之后就直接开始使用指针
### 编译链接
#### 各平台文件格式
平台 | 可执行文件 | 目标文件 | 动态库/共享对象 | 静态库
---|---|---|---|---
Windows|exe|obj|dll|lib
Unix/Linux|ELF、out|o|so|a
Mac|Mach-O|o|dylib、tbd、framework|a、framework
#### 编译链接过程
1. 预编译(预编译器处理如 `#include`、`#define` 等预编译指令,生成 `.i` 或 `.ii` 文件)
2. 编译(编译器进行词法分析、语法分析、语义分析、中间代码生成、目标代码生成、优化,生成 `.s` 文件)
3. 汇编(汇编器把汇编码翻译成机器码,生成 `.o` 文件)
4. 链接(连接器进行地址和空间分配、符号决议、重定位,生成 `.out` 文件)
> 现在版本 GCC 把预编译和编译合成一步,预编译编译程序 cc1、汇编器 as、连接器 ld
> MSVC 编译环境,编译器 cl、连接器 link、可执行文件查看器 dumpbin
#### 目标文件
编译器编译源代码后生成的文件叫做目标文件。目标文件从结构上讲,它是已经编译后的可执行文件格式,只是还没有经过链接的过程,其中可能有些符号或有些地址还没有被调整。
> 可执行文件(Windows 的 `.exe` 和 Linux 的 `ELF`)、动态链接库(Windows 的 `.dll` 和 Linux 的 `.so`)、静态链接库(Windows 的 `.lib` 和 Linux 的 `.a`)都是按照可执行文件格式存储(Windows 按照 PE-COFF,Linux 按照 ELF)
##### 目标文件格式
* Windows 的 PE(Portable Executable),或称为 PE-COFF,`.obj` 格式
* Linux 的 ELF(Executable Linkable Format),`.o` 格式
* Intel/Microsoft 的 OMF(Object Module Format)
* Unix 的 `a.out` 格式
* MS-DOS 的 `.COM` 格式
> PE 和 ELF 都是 COFF(Common File Format)的变种
##### 目标文件存储结构
段 | 功能
--- | ---
File Header | 文件头,描述整个文件的文件属性(包括文件是否可执行、是静态链接或动态连接及入口地址、目标硬件、目标操作系统等)
.text section | 代码段,执行语句编译成的机器代码
.data section | 数据段,已初始化的全局变量和局部静态变量
.bss section | BSS 段(Block Started by Symbol),未初始化的全局变量和局部静态变量(因为默认值为 0,所以只是在此预留位置,不占空间)
.rodata section | 只读数据段,存放只读数据,一般是程序里面的只读变量(如 const 修饰的变量)和字符串常量
.comment section | 注释信息段,存放编译器版本信息
.note.GNU-stack section | 堆栈提示段
> 其他段略
#### 链接的接口————符号
在链接中,目标文件之间相互拼合实际上是目标文件之间对地址的引用,即对函数和变量的地址的引用。我们将函数和变量统称为符号(Symbol),函数名或变量名就是符号名(Symbol Name)。
如下符号表(Symbol Table):
Symbol(符号名) | Symbol Value (地址)
--- | ---
main| 0x100
Add | 0x123
... | ...
### Linux 的共享库(Shared Library)
Linux 下的共享库就是普通的 ELF 共享对象。
共享库版本更新应该保证二进制接口 ABI(Application Binary Interface)的兼容
#### 命名
`libname.so.x.y.z`
* x:主版本号,不同主版本号的库之间不兼容,需要重新编译
* y:次版本号,高版本号向后兼容低版本号
* z:发布版本号,不对接口进行更改,完全兼容
#### 路径
大部分包括 Linux 在内的开源系统遵循 FHS(File Hierarchy Standard)的标准,这标准规定了系统文件如何存放,包括各个目录结构、组织和作用。
* `/lib`:存放系统最关键和最基础的共享库,如动态链接器、C 语言运行库、数学库等
* `/usr/lib`:存放非系统运行时所需要的关键性的库,主要是开发库
* `/usr/local/lib`:存放跟操作系统本身并不十分相关的库,主要是一些第三方应用程序的库
> 动态链接器会在 `/lib`、`/usr/lib` 和由 `/etc/ld.so.conf` 配置文件指定的,目录中查找共享库
#### 环境变量
* `LD_LIBRARY_PATH`:临时改变某个应用程序的共享库查找路径,而不会影响其他应用程序
* `LD_PRELOAD`:指定预先装载的一些共享库甚至是目标文件
* `LD_DEBUG`:打开动态链接器的调试功能
#### so 共享库的编写
使用 CLion 编写共享库
创建一个名为 MySharedLib 的共享库
CMakeLists.txt
```cmake
cmake_minimum_required(VERSION 3.10)
project(MySharedLib)
set(CMAKE_CXX_STANDARD 11)
add_library(MySharedLib SHARED library.cpp library.h)
```
library.h
```cpp
#ifndef MYSHAREDLIB_LIBRARY_H
#define MYSHAREDLIB_LIBRARY_H
// 打印 Hello World!
void hello();
// 使用可变模版参数求和
template