ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

数据库管理系统基础:从文件系统到关系模型与事务并发控制

数据库管理系统基础:从文件系统到关系模型与事务并发控制 如果你今天是自己搭了个数据库表明天就被数据一致性、并发写入、权限混乱的问题追着跑那这篇文章就是帮你把“数据库管理系统”这块地基一次补齐的。很多人花了很多时间学 SQL 语法却始终没想清楚一个问题数据库管理系统DBMS到底在系统里承担什么角色它凭什么能把数据托管得比文件更安全、更高效、更可靠这篇文章围绕“数据库管理系统基础”做一次系统梳理。从文件系统的痛点出发讲清楚数据库、数据库管理系统、数据库系统之间的层次关系再拆解关系模型、SQL 实操、事务与并发控制最后给出常见误区与工程建议。无论你是刚开始学数据库的初学者还是用过一段时间但基础不牢的开发者这篇文章都适合收藏后认真读一遍。1. 这篇数据库基础文章到底在讲什么先给读者画个像。你大概是这三类人之一计算机专业学生正在上数据库系统概论课概念听懂了但不知道每个概念对应真实系统里的什么环节。转行开发者已经会写 CRUD但没系统学过数据库原理面试时一被问到“事务隔离级别”“范式设计”就心虚。初级后台开发项目里因为缺约束、缺事务、权限混乱吃过亏想回头把基础补扎实。本文的主要内容并不是教你在某个数据库里执行多少条花哨的 SQL而是帮你建立一套理解数据库的框架。框架一旦建立你再看 MySQL、PostgreSQL、Oracle会发现它们本质上都遵循同样的核心逻辑用统一的模型组织数据用标准化的语言操纵数据用并发控制和恢复机制保证数据始终处于可靠状态。需要提醒的是标题里提到的 Neso Academy 数据库系统基础公开课是很好的外部补充资源。它的特点是用系统的计算机视角讲数据库概念推进很稳。你可以把它和理解这篇博客搭配着看视频负责建立直觉本文负责给出一份可检索、可落地、带实操的速查笔记。两者结合效果会好很多。2. 为什么需要数据库管理系统先看清文件系统的瓶颈想理解数据库管理系统为什么会出现最好的方式是先看没有它的时候程序员是怎么存数据的。早期阶段数据通常以文件形式保存。业务简单时一个 CSV 文件、一个 JSON 文件就能满足需求。但一旦数据量变大、业务逻辑变复杂文件存储会迅速暴露出一堆问题。2.1 数据冗余与更新异常同一个信息可能被复制到多个文件中。比如客户姓名同时出现在订单文件、物流文件、售后文件中。当客户改名时你需要把所有文件都改一遍。一旦漏改同一个客户在不同系统里就会出现不同的名字。这就是数据冗余带来的更新异常。2.2 并发访问难以控制两个用户同时修改同一个文件后写入的人很可能直接覆盖先写入的人。没有锁机制、没有事务隔离程序只能依赖“尽量少同时操作同一份文件”的侥幸。在真实业务里这种侥幸大概率会变成事故。2.3 程序与数据结构强耦合文件格式一旦变动所有读取该文件的程序都要跟着改。如果字段顺序、分隔符、编码方式发生变化涉及的程序可能多达几十处。这种耦合让系统维护成本居高不下。2.4 缺少统一的安全管理文件系统的权限控制粒度很粗通常只能控制到“文件能不能读、能不能写”。但你往往希望做到“这个用户只能读某些列不能改某些表”。传统文件方式很难做到。数据库管理系统就是为了解决这些问题而生的软件系统。它不只是在“存数据”这件事上做得更好而是把抽象提到了数据层你按照逻辑结构定义数据、操作数据物理存储和访问细节由 DBMS 负责。这种抽象才是它最核心的价值。小结论文件系统适合存储简单、低并发、无强一致要求的静态数据一旦业务需要共享、并发、权限控制和可靠性保证就到了引入数据库管理系统的时刻。3. 数据库、数据库管理系统、数据库系统三个概念别再用混很多文章把这几个词混着用导致初学者越看越糊涂。其实这三个概念是不同层次的东西。概念英文含义通俗类比数据库DataBaseDB存储在计算机内有组织、可共享的数据集合仓库里的货物本身数据库管理系统DataBase Management SystemDBMS位于用户与操作系统之间的数据管理软件负责定义、创建、维护、操纵数据库仓库里的货物管理系统数据库系统DataBase SystemDBS数据库 数据库管理系统 应用程序 数据库管理员 用户整个仓库运营体系包括人、货、设备、流程这里要展开讲一下。数据库DB强调的是数据本身。它是按照某种数据模型组织起来的长期存储在计算机内可以被多个用户共享的数据集合。比如“学生信息库”里存着学生表、课程表、选课表这些数据集合在一起就是数据库。数据库管理系统DBMS是软件是管理数据库的工具。MySQL、Oracle、PostgreSQL、SQL Server这些都是 DBMS。它们负责建表、查数据、加索引、管权限、做事务、出备份所有这些能力都属于 DBMS 的职责范围。数据库系统DBS的范围最大。除了数据库和 DBMS还包括应用系统、数据库管理员DBA以及终端用户。一个正在运行的在线教育系统背后有数据库、有 MySQL 实例、有业务应用、有运维人员这一整套可以称为数据库系统。平时大家口语说“我们用 MySQL 存数据”其实是省略了“关系型数据库管理系统”这个完整名称。MySQL 不是“数据库”本身至少要创建一个 database 之后才有人在里面真正存放数据。这种概念辨析并不是扣字眼。理解三个概念的边界你在阅读官方文档、参与架构评审、讨论数据迁移时才能和同伴使用同一套语言。4. 数据库管理系统的内部构成到底由什么在支撑运行如果你把数据库管理系统当作一个黑盒那它输入的是 SQL 语句输出的是数据结果。但作为一个合格的开发者至少要知道黑盒内部有哪几个关键模块出了问题才能定位。4.1 两大核心组件从功能上划分数据库管理系统内部可以分成查询处理器和存储管理器两大部分。模块主要子部件职责查询处理器DDL 编译器、DML 编译器、查询优化器把 SQL 翻译成可执行计划并选择代价更低的执行路径存储管理器权限与完整性管理器、事务管理器、缓冲区管理器、文件管理器负责数据在磁盘和内存之间的读写维护约束与权限管理事务的提交与回滚查询处理器做的事情可以通过一条查询语句来理解SELECT * FROM student WHERE major_id 1;这条 SQL 到达数据库后DBMS 会先做语法解析、语义检查生成逻辑计划然后交给优化器生成物理执行计划。优化器决定是走索引还是全表扫描是使用嵌套循环连接还是哈希连接。这些决策直接决定了你的 SQL 跑得快还是慢。存储管理器做的事情发生在你执行写入操作时。它要把数据写进缓冲区再由缓冲区刷到磁盘文件它要检查插入的数据是否违反非空约束、唯一约束、外键约束它还要记录事务日志保证系统突然崩溃后可以恢复。没有这些底层模块你执行一条 INSERT 语句就可能破坏整个数据库的一致性。很多开发者在业务中遇到“数据怎么多了”“数据怎么丢了”查到最后往往就是某个底层机制没理清楚。4.2 三层模式结构与两级映射理解数据库管理系统还有一个绕不开的结构三层模式。外模式也叫用户模式或子模式是用户能看到和操作的数据视图。一个数据库可以有多个外模式对应不同用户的不同需求。概念模式也叫逻辑模式描述数据库中全部数据的逻辑结构。它处于中间层是数据库设计者视角下的全局逻辑结构。内模式也叫存储模式描述数据在物理存储介质上的存储方式和访问方式。两层映射是连接它们的桥梁外模式/概念模式映射保证概念模式发生变化时外模式可以保持不变从而应用程序不必修改。这叫逻辑独立性。概念模式/内模式映射保证内模式发生变化时比如存储引擎更换、数据文件重新组织概念模式不受影响。这叫物理独立性。理解三层模式和两级映射后你就会明白一个常见问题的答案为什么业务系统可以比较平滑地从 Oracle 迁移到 PostgreSQL因为应用通过 SQL 访问的是外模式只要逻辑模式不变底层物理存储怎么调整对应用层面是透明的。这就是数据库管理系统抽象能力的一个直接体现。5. 关系模型与完整性约束数据不混乱的根本保证在所有数据模型中关系模型是当前商业数据库的主流。它由 E. F. Codd 在 1970 年提出理论基础是集合论和关系代数。关系模型受欢迎是因为它足够简单数据组织成二维表表之间通过公共属性建立联系查询可以用非过程化的 SQL 表示用户不需要关心底层访问路径。5.1 关系模型的基本术语关系一张二维表。元组表中的一行。属性表中的一列。候选键能唯一标识一个元组的最小属性集合。主键从候选键中选定一个用于唯一标识每一行。外键一个关系中的属性它引用另一个关系的主键用于表达关系之间的连接。域属性的取值范围。新手最容易犯的错误是把主键简单理解为唯一索引。主键不仅要求唯一还要求不能为空。这是关系模型对数据完整性的一个基本保证。5.2 三种完整性约束完整性约束是关系模型最有价值的部分也是很多实际项目中被低估的部分。约束类型名称规则违反后果示例实体完整性Entity Integrity主属性不能取空值且取值唯一插入两行相同 student_id 的数据参照完整性Referential Integrity外键取值要么为空要么等于被引用表中某行的主键值学生记录了不存在的专业编号用户定义完整性User-defined Integrity非空、唯一、CHECK 条件等业务规则年龄列被写入负数没有约束时数据库可以往里塞任何数据。比如学生表里插入一条记录major_id 指向一个根本不存在的专业。单条数据看着不碍事但做统计报表时关联不上专业表的数据就会变成脏数据并且很难追溯。有约束时数据库就在源头拒绝了不合规的写入。这才是真正的数据安全。很多团队对约束有误解觉得外键影响性能就不用这其实是把性能优化和正确性对立的错误方式。正确的做法是先保证正确性再通过索引、缓存、分区等手段解决性能瓶颈。完整性约束的设计应该在建表阶段完成而不是等项目上线后再补。数据库领域有一条规律在源头拒绝坏数据永远比事后清洗坏数据便宜得多。6. SQL 分层与完整实操示例SQL 是关系数据库的标准操作语言。它内部又分成多个子语言不同子语言负责不同职责。子语言全称职责DDLData Definition Language定义库、表、索引、视图等结构DMLData Manipulation Language插入、更新、删除数据DQLData Query Language查询数据DCLData Control Language控制权限与访问范围TCLTransaction Control Language控制事务提交、回滚下面用一个“学生选课管理”的小场景走一遍常用 SQL。6.1 用 DDL 建库建表约束在源头设计以 MySQL 8.0 为例但下面语句在 5.7 也能运行。如果本地没有 MySQL可以在 Docker 中快速启动一个示例docker run --name mysql-demo \ -e MYSQL_ROOT_PASSWORDroot123456 \ -e MYSQL_DATABASEstudent_db \ -p 3306:3306 \ -d mysql:8.0创建数据库和表CREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARACTER SET utf8mb4; USE student_db; CREATE TABLE major ( major_id INT PRIMARY KEY AUTO_INCREMENT, major_name VARCHAR(64) NOT NULL UNIQUE, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE student ( student_id CHAR(8) PRIMARY KEY, name VARCHAR(32) NOT NULL, gender ENUM(M, F) NOT NULL, major_id INT NOT NULL, enroll_year YEAR NOT NULL, CONSTRAINT fk_student_major FOREIGN KEY (major_id) REFERENCES major(major_id) );这段 DDL 有几个关键点需要理解PRIMARY KEY同时保证唯一和非空这是实体完整性。NOT NULL和UNIQUE属于用户定义完整性直接约束业务规则。FOREIGN KEY将 student 表和 major 表连接起来保证 student 中的 major_id 一定是 major 表中真实存在的专业这是参照完整性。字符集使用utf8mb4避免中文和特殊字符出现乱码。6.2 用 DML/DQL 写数据、查数据插入数据INSERT INTO major (major_name) VALUES (软件工程), (网络工程), (大数据); INSERT INTO student (student_id, name, gender, major_id, enroll_year) VALUES (20230001, 张同学, M, 1, 2023), (20230002, 李同学, F, 2, 2023), (20230003, 王同学, M, 3, 2024);查询数据SELECT s.student_id, s.name, m.major_name FROM student s JOIN major m ON s.major_id m.major_id WHERE m.major_name 软件工程;预期输出------------------------------------ | student_id | name | major_name | ------------------------------------ | 20230001 | 张同学 | 软件工程 | ------------------------------------JOIN 的作用是拿到两张表相关联的数据。如果当初不设置外键这里的关联条件完全依赖于人工约定一旦数据被写坏查询结果就会不准确。尝试插入一条违反外键约束的数据INSERT INTO student (student_id, name, gender, major_id, enroll_year) VALUES (20230099, 错误同学, M, 999, 2024);数据库会拒绝执行并返回外键约束失败的错误。这个拒绝行为就是完整性约束在起保护作用。6.3 用 DCL 控制权限遵守最小权限原则生产环境不建议业务服务直接使用 root 账号连接数据库。更合理的做法是为不同服务创建不同账号只授予必要权限。-- 创建只读账号 CREATE USER app_read% IDENTIFIED BY StrongPss2025; -- 只允许查询 student_db 下的所有表 GRANT SELECT ON student_db.* TO app_read%; -- 创建读写账号 CREATE USER app_write% IDENTIFIED BY AnotherPss2025; GRANT SELECT, INSERT, UPDATE, DELETE ON student_db.* TO app_write%; -- 刷新权限 FLUSH PRIVILEGES;这里要特别强调权限控制不是可有可无的规范而是安全底线。只读账号即使泄露攻击者也无法篡改数据业务账号即使出错影响范围也被限制在指定库表内。DCL 的使用应该从第一天学数据库就开始养成习惯。6.4 用 TCL 管理事务保证数据的一致性以账户转账为例事务控制语句如下START TRANSACTION; UPDATE account SET balance balance - 500 WHERE account_id 1001; UPDATE account SET balance balance 500 WHERE account_id 1002; COMMIT;第一条 UPDATE 成功后、第二条 UPDATE 还没执行时如果系统突然崩溃数据库会自动回滚账户 1001 的扣款不会遗留。手动回滚的写法是ROLLBACK;事务是数据库可靠性的基石。后面单独用一章展开讲。7. 事务与并发数据库可靠性的最后防线事务是数据库管理系统保证数据一致性的核心机制。它把一组操作打包成一个不可分割的执行单元要么全部成功要么全部失败。7.1 事务的 ACID 特性特性英文含义原子性Atomicity事务内所有操作作为一个整体不能只执行一部分一致性Consistency事务执行前后数据库都处于合法状态完整性约束满足隔离性Isolation并发执行的事务之间互不干扰持久性Durability事务提交后数据修改永久保存很多人背得出 ACID但真正设计系统时却不用事务。比如批量修改数据时逐条 UPDATE中途一条失败前面已经改掉的数据无法自动回滚最终留下半成品数据。这就是没有正确使用事务的典型问题。7.2 并发事务带来的三类问题两个事务同时操作同一份数据时会出现以下问题问题描述脏读一个事务读到另一个事务未提交的数据。如果对方回滚读到的就是错误的临时数据不可重复读一个事务内两次读取同一行数据结果不同。原因是另一个事务在期间修改并提交了该行幻读一个事务内两次执行同一查询结果集的行数不同。原因是另一个事务在期间插入了新行7.3 隔离级别数据库管理系统通过隔离级别来解决并发问题。SQL 标准定义了四个隔离级别从低到高隔离级别脏读不可重复读幻读READ UNCOMMITTED可能可能可能READ COMMITTED不可能可能可能REPEATABLE READ不可能不可能可能SERIALIZABLE不可能不可能不可能隔离级别越高一致性越强并发能力往往越弱。MySQL InnoDB 引擎默认使用 REPEATABLE READPostgreSQL 默认使用 READ COMMITTED。实际项目中要根据业务对一致性的要求做选择而不是盲目追求最高隔离级别。高隔离级别下事务等待和死锁的概率也会上升。遇到死锁时数据库管理系统会自动检测并牺牲一个事务让它回滚从而让另一个事务继续执行。开发者需要做的是尽量把事务持续时间缩短避免大事务长时间占用资源。8. 数据库系统基础常见误区与排查思路下面这些误区在初学者和早期工程师中非常常见。整理成表格方便查阅。问题现象可能原因排查方式解决方案主键允许插入 NULL混淆唯一索引与主键的定义检查表结构查看约束定义主键同时要求非空、唯一设计表时严格约束关联查询查不到数据外键数据不一致存在孤儿数据使用 LEFT JOIN 找出未匹配记录在源头增加外键约束必要时清理已有脏数据查询越来越慢缺少索引SQL 走了全表扫描执行 EXPLAIN 查看执行计划为常用查询条件建立合适的索引数据更新后出现半成品状态多条 DML 语句没有放在同一事务里查看业务日志检查事务控制语句用事务包裹多条操作异常时回滚两个事务互相等待全部失败并发更新同一批数据导致死锁查看数据库锁等待日志调整事务访问顺序缩短事务时间业务账号权限过大误删数据使用 root 账号直连业务库审计账号权限与连接方式按最小权限原则创建专用账号线上执行 DDL 导致锁表表数据量大DDL 在线变更受限查看数据库 DDL 执行状态与锁等待使用在线 DDL 工具低峰期执行并做好备份排查数据库问题第一步永远是看日志。MySQL 的错误日志、慢查询日志、事务回滚日志都是定位问题的第一手资料。第二步用 EXPLAIN 分析执行计划判断 SQL 是否走了预期索引。第三步查看锁等待和事务状态判断是否存在并发冲突。不要一上来就猜、就改配置那样往往会把问题弄得更隐蔽。9. 数据库学习路线与工程实践建议9.1 初学者建议按这条路径走学数据库管理系统基础不要急于追分布式、不要一上来就看分库分表。先按下面顺序建立体系概念层理解数据库、DBMS、DBS 的区别掌握三层模式和两级映射。关系模型层熟悉关系、元组、主键、外键、完整性约束。这是所有关系数据库的基础。SQL 实操层在一台本机 MySQL 或 PostgreSQL 上完成建库、建表、增删改查、权限控制。事务与并发层动手演示脏读、不可重复读、幻读理解隔离级别的差异。设计层学习 ER 模型和范式理论练习把一个业务场景设计成三范式表结构。性能层学习索引原理用 EXPLAIN 分析 SQL 执行计划。每一步都要配合动手实验。只看书、只背定义数据库是学不会的。推荐自己做一个最小选课系统包含学生、课程、选课记录三张表然后把约束、事务、索引、视图全用一遍。做完之后你对数据库基础的理解会明显上一个台阶。9.2 工程实践建议规范命名表名、字段名使用统一风格比如小写字母加下划线避免在代码中到处大小写转换。备份先行任何涉及生产数据的变更都要先确认备份和回滚方案。变更评审DDL 变更尽量通过工单流程评审不要直接在生产环境执行。权限最小化业务账号永远不要使用 root权限范围越小越好。事务短而快避免在事务里做远程调用、耗时的文件操作事务时间越短锁竞争越小。留好监控至少掌握慢查询日志和连接数监控这是发现数据库问题的第一个窗口。数据库系统的工程能力和基础概念是相辅相成的。理论让你知道边界在哪里工程实践让你知道这个边界在真实系统中意味着什么。10. 写在最后数据库管理系统不是“装个 MySQL、会写几条 SQL”这么简单。它是一整套关于数据组织、约束、安全、并发和恢复的系统性方案。这篇文章帮你把几件关键事串了起来文件系统为什么会被数据库替代数据库管理系统内部有哪些模块关系模型和完整性约束为什么能保证数据不混乱SQL 各个子语言分别负责什么事务和隔离级别怎么保护系统并发时的可靠性以及初学者最容易踩的坑。建议你别把本文只当科普读。打开终端建一个学生选课库把主键、外键、非空约束、唯一约束、事务提交和回滚全部敲一遍。真正跑通之后你再看任何一本数据库教材、任何一门公开课都会有完全不同的体感。数据库的基础决定了你能走多远。把这块补齐比追任何新技术都更值得。
返回列表