第一阶段:安装与环境配置
这一阶段的核心目标是用最短时间、最顺畅的方式让你拥有一个可以动手实践的 PostgreSQL 环境。我们将分平台介绍,请按你的操作系统选择。
1. PostgreSQL 安装(各平台)
A. Windows 平台安装(推荐最简单的安装器)
步骤 1:下载安装器
- 前往 PostgreSQL 官方下载页面
- 点击 Download the installer
- 选择适合自己系统(64位或32位)的版本下载。例如:
PostgreSQL 15.xfor Windows x86-64。
步骤 2:运行安装
-
双击下载好的
.exe文件(如postgresql-15.x-windows-x64.exe)。 -
重要设置点:
-
安装路径:默认即可(
C:\Program Files\PostgreSQL\15)。 -
选择组件:务必勾选:
PostgreSQL ServerpgAdmin 4(这是GUI图形化管理工具)Command Line Tools(包含psql命令行工具)Stack Builder(可选,用于安装附加驱动)
-
数据目录:默认(
C:\Program Files\PostgreSQL\15\data)。 -
设置密码:这是你的 超级用户 (postgres) 密码!一定记住!例如:
mysecretpassword。 -
端口:默认
5432(除非该端口已被占用)。 -
语言环境:保持默认或选择
Chinese (Simplified), China。
-
步骤 3:完成安装
- 一路点击 “Next” 直到完成。在最后一步,不要取消勾选 “Launch Stack Builder? ”,直接点 “Finish”。
- 安装完成!Windows 的服务列表中会增加一个
postgresql-x64-15的服务,并自动启动。
B. macOS 平台安装(推荐两种方法)
方法 1:使用 Homebrew(最简单快捷,推荐开发者)
-
打开
终端。 -
如果你没有 Homebrew,先安装它:
<BASH> /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -
使用 Homebrew 安装 PostgreSQL:
<BASH> brew install postgresql@15 -
启动 PostgreSQL 服务(每次开机后可能需要运行一次):
<BASH> brew services start postgresql@15 -
注意:Homebrew 安装的 PostgreSQL,默认超级用户是你的系统用户名,且没有密码。数据目录通常在
/opt/homebrew/var/postgresql@15。
方法 2:官方图形化安装器
- 下载 EnterpriseDB 提供的 macOS 安装包。
- 运行
.dmg文件,像安装普通 App 一样拖拽即可。 - 安装过程与 Windows 版类似,会提示设置 postgres 用户的密码,并安装 pgAdmin。
C. Linux 平台(以 Ubuntu/Debian 为例)
使用 apt 包管理器安装:
<BASH>
# 1. 更新包列表
sudo apt update
# 2. 安装 PostgreSQL 和常用工具包
sudo apt install postgresql postgresql-contrib
# 3. 查看服务状态
sudo systemctl status postgresql
# 4. PostgreSQL 会自动启动。默认超级用户也叫 `postgres`。
重要:Linux 安装后,需要切换到 postgres 系统用户来操作数据库。
2. pgAdmin 工具的安装使用
A. pgAdmin 4 - PostgreSQL 官方 GUI 工具
-
如果你在 Windows/macOS 使用官方安装器,它已经一并安装了!
-
找到并启动它:在开始菜单(Windows)或启动台(macOS)搜索 “pgAdmin 4”。
-
首次连接配置:
-
启动后,它会要求你设置一个 主密码(Master Password) ,用于保护你的数据库连接信息。请牢记。
-
在左侧 “Browser” 窗口,右键点击
Servers->Register->Server...。 -
在 “General” 选项卡的 “Name” 里,随意起个名字,如
MyLocalPG。 -
在 “Connection” 选项卡:
- Host name/address:
localhost - Port:
5432 - Maintenance database:
postgres(默认数据库) - Username:
postgres(Windows/图形化安装器) 或你的系统用户名(macOS Homebrew安装) - Password: 你安装时设置的密码(如果是Homebrew无密码,则留空)
- Host name/address:
-
点击 “Save”。如果一切顺利,左侧就能展开看到你的数据库服务器和其中的数据库了。
-
pgAdmin 界面概览:
- 左侧浏览器:管理服务器、数据库、表等对象。
- 顶部工具栏:执行查询、导入导出等。
- 中部主窗口:查询工具、仪表板等。
3. 命令行工具 psql 的基本操作
这是最重要的一步,无论 GUI 多方便,psql 命令行依然是管理和调试数据库最可靠、最高效的方式。
如何启动 psql
-
Windows:
- 方法 1:在开始菜单找到 “SQL Shell (psql)” 并打开。
- 方法 2:在
cmd或PowerShell中直接输入psql -U postgres。
-
macOS / Linux:
-
打开终端。
-
关键步骤:需要以正确的用户身份登录。
- 如果你是 官方安装器/apt安装:
sudo -u postgres psql - 如果你是 macOS Homebrew 安装:
psql postgres(直接用你的用户名)
- 如果你是 官方安装器/apt安装:
-
psql 基础命令(交互式命令,以 `` 开头)
当你看到 postgres=# 这样的提示符时,说明你已经成功连接!
# 1. 列出所有数据库
\l
或
\l+
# 2. 连接到另一个数据库 (假设有一个叫 mydb 的数据库)
\c mydb
# 3. 列出当前数据库的所有表
\dt
# 4. 查看表结构 (例如查看 users 表)
\d users
\d+ users # 更详细
# 5. 列出所有角色(用户)
\du
# 6. 执行外部 SQL 文件
\i /path/to/your/file.sql
# 7. 开启执行时间计时
\timing
# 8. 设置输出格式 (更易读)
\x auto
# 9. 退出 psql
\q
在 psql 中执行 SQL 语句
直接输入 SQL 语句,以分号 (;) 结尾,然后按回车执行。
-- 示例:创建一个测试数据库
CREATE DATABASE testdb;
-- 连接到新数据库
\c testdb
-- 创建一张表
CREATE TABLE person (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT
);
-- 插入一些数据
INSERT INTO person (name, age) VALUES ('张三', 25), ('李四', 30);
-- 查询数据
SELECT * FROM person;
-- 更新数据
UPDATE person SET age = 26 WHERE name = '张三';
-- 删除数据
DELETE FROM person WHERE name = '李四';
本阶段实战任务(必须完成)
-
成功安装 PostgreSQL 在你的操作系统上。
-
成功连接:
- 使用
psql命令行连接到postgres数据库。 - (可选但推荐)使用 pgAdmin 或 DBeaver 图形化连接。
- 使用
-
执行你的第一个 SQL:
-
通过
psql,完成以下操作:- 创建一个名为
myfirstdb的数据库。 - 连接到这个数据库。
- 创建一个
books表,包含id,title,author,price字段。 - 插入 2-3 条图书数据。
- 执行一次查询,显示所有图书。
- 创建一个名为
-
-
理解概念:
postgres既是默认数据库名,也是一个默认的超级用户名。localhost:5432是 PostgreSQL 默认的监听地址和端口。
ACID:数据库事务的四大保证
ACID 是数据库事务必须满足的四个关键特性,确保数据的可靠性和一致性。
ACID 定义
A - Atomicity 原子性
C - Consistency 一致性
I - Isolation 隔离性
D - Durability 持久性
1. 原子性 (Atomicity)
"要么全部完成,要么全部不完成"
通俗解释: 事务就像原子一样不可分割。要么所有操作都成功,要么全部回滚到事务开始前的状态。
例子: 银行转账
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE user = 'A'; -- A扣款
UPDATE accounts SET balance = balance + 100 WHERE user = 'B'; -- B收款
COMMIT;
如果第二步失败(B账户不存在),第一步的扣款操作会自动撤销。
2. 一致性 (Consistency)
"事务必须始终保持数据的完整性约束"
通俗解释: 事务前后,数据库都必须处于合法的状态,遵守所有的规则和约束。
约束类型:
- 主键约束:主键必须唯一
- 外键约束:外键必须引用有效记录
- 唯一约束:某些列值不能重复
- 数据范围:如余额不能为负数
例子:
-- 错误:转账金额大于余额
UPDATE accounts SET balance = balance - 1000 WHERE balance = 500;
-- 事务会失败,因为余额不能为负数
3. 隔离性 (Isolation)
"并发事务互不干扰"
通俗解释: 多个事务同时执行时,它们各自的操作应该像顺序执行一样,互不影响。
隔离级别:
-- PostgreSQL 隔离级别
SET TRANSACTION ISOLATION LEVEL
READ UNCOMMITTED -- 可能读到脏数据(最低)
| READ COMMITTED -- 只能读已提交的数据(默认)
| REPEATABLE READ -- 可重复读
| SERIALIZABLE; -- 完全隔离(最高)
1. 读未提交 (READ UNCOMMITTED)
最低隔离级别:可能读取到其他事务未提交的数据
PostgreSQL 实际不支持这个级别(它直接升级为 READ COMMITTED) 但概念很重要:
-- 会话A
BEGIN;
UPDATE accounts SET balance = 500 WHERE id = 1;
-- 还没提交!
-- 会话B (READ UNCOMMITTED 下)
BEGIN TRANSACTION ISOLATION LEVEL ...;
SELECT balance FROM accounts WHERE id = 1;
-- ❌ 可能看到 500(脏读)
-- 如果A回滚,B看到的数据就是错的!
现实比喻:看到同事写了半截的邮件,结果他删掉不发了
2. 读已提交 (READ COMMITTED)
PostgreSQL 默认级别:只能读取已提交的数据
-- 演示:两个转账同时进行
CREATE TABLE accounts (
id INT PRIMARY KEY,
name VARCHAR(50),
balance DECIMAL(10,2)
);
INSERT INTO accounts VALUES
(1, '小明', 1000),
(2, '小红', 1000);
-- 会话A:小明转200给小红
BEGIN; -- PostgreSQL默认READ COMMITTED
UPDATE accounts SET balance = balance - 200 WHERE id = 1; -- 小明变800
-- 还没提交...
-- 会话B:查看余额
BEGIN;
SELECT balance FROM accounts WHERE id = 1;
-- ✅ 结果:1000(看到的是事务开始前的快照)
-- 会话A提交
COMMIT;
-- 会话B再次查询
SELECT balance FROM accounts WHERE id = 1;
-- ✅ 结果:800(看到新提交的数据)
COMMIT;
但有问题:不可重复读
-- 会话A
BEGIN;
-- 第一次查询
SELECT SUM(balance) FROM accounts;
-- 结果:2000
-- 会话B(同时)
BEGIN;
UPDATE accounts SET balance = balance + 500 WHERE id = 1;
COMMIT; -- 提交了!
-- 会话A 再次查询
SELECT SUM(balance) FROM accounts;
-- ❌ 结果:2500(和第一次不一样!)
COMMIT;
3. 可重复读 (REPEATABLE READ)
同一事务内,多次读取同一数据结果一致
-- 会话A
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 第一次查询
SELECT balance FROM accounts WHERE id = 1;
-- 结果:800
-- 会话B(更新并提交)
BEGIN;
UPDATE accounts SET balance = 1000 WHERE id = 1;
COMMIT;
-- 会话A 第二次查询(在同一事务内)
SELECT balance FROM accounts WHERE id = 1;
-- ✅ 结果:800(和第一次一样,不受B影响)
COMMIT; -- 提交后才看到1000
现实比喻:
- 你早上8点打开报表,一直看到10点
- 别人9点更新了数据
- 但你看到的还是8点时的数据快照
🔴 但还有问题:幻读 (Phantom Read)
-- 会话A(统计用户)
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT COUNT(*) FROM accounts WHERE balance > 500;
-- 结果:2
-- 会话B(插入新用户)
BEGIN;
INSERT INTO accounts VALUES (3, '小刚', 600);
COMMIT;
-- 会话A 再次统计
SELECT COUNT(*) FROM accounts WHERE balance > 500;
-- ✅ 结果:2(不会看到新用户)
COMMIT;
等等,这不是没问题吗? 看这个:
-- 会话A(想找出所有余额>500的用户)
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT id FROM accounts WHERE balance > 500;
-- 返回:1, 2
-- 会话B(插入新用户)
BEGIN;
INSERT INTO accounts VALUES (3, '小刚', 600);
COMMIT;
-- 会话A 尝试更新这些用户
UPDATE accounts SET balance = balance * 1.1
WHERE balance > 500;
-- ❌ PostgreSQL会报错:ERROR: could not serialize access
-- 因为发现条件范围被修改了
4. 序列化 (SERIALIZABLE)
最高隔离级别:完全串行执行的效果
-- 经典的"丢失更新"问题演示
-- 会话A
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT balance FROM accounts WHERE id = 1;
-- 看到:800(想加400奖金)
-- 会话B(同时)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT balance FROM accounts WHERE id = 1;
-- 同样看到:800(想扣300罚款)
-- 会话A
UPDATE accounts SET balance = 800 + 400 WHERE id = 1;
COMMIT; -- 成功,余额变1200
-- 会话B
UPDATE accounts SET balance = 800 - 300 WHERE id = 1;
-- ❌ ERROR: could not serialize access due to concurrent update
ROLLBACK; -- 必须重试
现实比喻:
- 两个售票员同时卖最后一张票
- 系统只让一个人成功,另一个失败重试
- 避免"一票两卖"
4. 持久性 (Durability)
"一旦提交,永不丢失"
通俗解释: 事务提交后,即使系统崩溃、断电,数据也不会丢失。
实现机制:
┌─────────────────────────────────────┐
│ PostgreSQL 持久化保证 │
├─────────────────────────────────────┤
│ 1. WAL(Write-Ahead Logging) │
│ 先写日志,再写数据 │
│ │
│ 2. Checkpoint │
│ 定期将内存数据刷到磁盘 │
│ │
│ 3. 同步提交 │
│ 确保日志写入磁盘后才返回成功 │
└─────────────────────────────────────┘
关系型数据库 vs 非关系型数据库
关系型数据库 (RDBMS)
特点:
- 使用表格(Table)存储数据,行=记录,列=字段
- 遵循ACID原则(原子性、一致性、隔离性、持久性)
- 使用SQL语言操作
- 数据间有关联(外键)
代表产品:
- MySQL
- PostgreSQL
- Oracle
- SQL Server
适用场景:
- 需要复杂查询和事务处理的场景
- 数据结构固定、关系明确的应用
- 银行系统、ERP系统等
非关系型数据库 (NoSQL)
特点:
- 不使用固定表格结构
- 灵活的数据模型
- 高可扩展性和高性能
- 不强制要求ACID特性
四种主要类型:
| 类型 | 特点 | 代表产品 | 适用场景 |
|---|---|---|---|
| 文档型 | 类似JSON格式存储 | MongoDB | 内容管理系统 |
| 键值型 | 简单的键值对 | Redis | 缓存、会话存储 |
| 列存储 | 按列组织数据 | Cassandra | 大数据分析 |
| 图数据库 | 存储节点和关系 | Neo4j | 社交网络、推荐系统 |
二、数据库关系类型
1. 一对一关系
概念: 一个表的每条记录对应另一个表的仅一条记录。
现实举例:
- 用户 ↔ 用户身份证信息
- 学生 ↔ 学籍档案(一对一)
SQL实现:
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50)
);
-- 身份证表(外键引用用户id)
CREATE TABLE id_cards (
user_id INT PRIMARY KEY,
id_number VARCHAR(20),
FOREIGN KEY (user_id) REFERENCES users(id)
-- 也可以添加 UNIQUE 约束确保一对一
);
2. 一对多关系
概念: 一个表的记录对应另一个表的多条记录。
现实举例:
- 部门 → 员工(一个部门有多个员工)
- 班级 → 学生(一个班级多个学生)
- 用户 → 订单(一个用户多个订单)
SQL实现:
-- "一"方:部门表
CREATE TABLE departments (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(50)
);
-- "多"方:员工表(包含外键)
CREATE TABLE employees (
emp_id INT PRIMARY KEY,
emp_name VARCHAR(50),
dept_id INT, -- 外键字段
FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);
3. 多对多关系
概念: 两个表的记录可以相互对应多条记录。
现实举例:
- 学生 ↔ 课程(一个学生选多门课,一门课多个学生选)
- 产品 ↔ 订单(一个订单多种产品,一个产品在多个订单中)
- 作者 ↔ 书籍(一个作者多本书,一本书多个作者)
SQL实现: 需要中间表(连接表) :
<SQL>
-- 学生表
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(50)
);
-- 课程表
CREATE TABLE courses (
course_id INT PRIMARY KEY,
course_name VARCHAR(50)
);
-- 中间表(连接表)
CREATE TABLE student_courses (
student_id INT,
course_id INT,
enrollment_date DATE,
PRIMARY KEY (student_id, course_id), -- 复合主键
FOREIGN KEY (student_id) REFERENCES students(student_id),
FOREIGN KEY (course_id) REFERENCES courses(course_id)
);
三、视觉化对比
一对一关系:
<TEXT>
用户表 身份证表
┌─────┐ ┌───────────┐
│用户A│─────→│身份证A │
├─────┤ ├───────────┤
│用户B│─────→│身份证B │
└─────┘ └───────────┘
一对多关系:
<TEXT>
部门表 员工表
┌─────┐ ┌──────┐
│IT部 │──┐ │小王 │ ←─┐
├─────┤ ├─→ │小李 │ │
│HR部 │──┤ ├──────┤ │
└─────┘ └─→ │小张 │ │
└──────┘ │
部门ID指向IT部
多对多关系:
<TEXT>
学生表 中间表 课程表
┌─────┐ ┌───────┐ ┌──────┐
│张三 │─────→│张 数学│←──│数学 │
├─────┤ ├───────┤ ├──────┤
│李四 │─────→│张 英语│ │英语 │
│ │ ├───────┤ ├──────┤
│ │ │李 数学│ │物理 │
└─────┘ │李 物理│ └──────┘
└───────┘
四、实际应用建议
选择建议:
- 需要事务和复杂查询 → 关系型数据库
- 快速扩展、灵活结构 → 非关系型数据库
- 混合架构:主流应用使用RDBMS + 特定功能使用NoSQL(如Redis缓存)
关系设计技巧:
- 分析业务需求时,先确定实体间的真实关系
- 多对多关系一定需要中间表
- 外键约束保证数据完整性,但可能影响性能
- 适当冗余可提高查询效率(空间换时间)