数据库架构回答的不是“数据库部署在哪里”这么简单。它要把处理器、内存、存储、网络和故障边界组织起来,再决定请求在哪一层执行、数据在哪一层保存、哪些资源可以共享,以及增加机器后性能能否随之增长。
同一个订单业务,可以运行在一台多核服务器上,也可以拆成浏览器、应用服务器和数据库服务器三层;数据库内部还可能由多个共享内存节点或无共享节点组成,并把副本放到异地数据中心。表结构和 SQL 看起来相同,通信代价、并发方式、扩容路径和故障处理却完全不同。

图:架构设计先识别计算、内存、存储和网络的边界,再决定客户端、服务端、并行节点与异地站点如何协作。
这篇内容按“单机内部—客户端与服务器—并行节点—跨地域—云服务”的顺序展开。重点不是记住架构名称,而是学会沿着请求路径判断:一次操作经过多少次网络往返,数据移动了多少,哪个共享资源最先拥塞,某个节点或站点失效后谁能接管。
数据库运行时会消耗五类关键资源:处理器执行查询与事务逻辑,内存保存缓冲页、锁表和执行状态,持久化设备保存数据与日志,互连网络搬运请求和数据,管理边界决定谁能配置、升级与恢复系统。所谓架构,就是规定这些资源如何归属、如何互通。
判断一套架构时,可以连续问五个问题:
这些问题比“单机还是分布式”更有辨识力。例如,两台服务器都能访问同一存储阵列,它们属于共享磁盘架构;两台服务器各有本地存储,通过消息交换数据,则更接近无共享架构。它们都使用多台机器,但扩展瓶颈和故障接管方式不同。
并发表示多个任务的执行区间重叠。在单个处理器上,操作系统也能通过时间片让多个事务交错执行。并行要求多个处理器或核心在同一时刻真正工作。分布则表示组件位于彼此独立、通过网络通信的节点或站点上;分布式系统可能并行处理,也可能只为数据共享和异地容灾而部署。
多核共享内存服务器通常属于粗粒度并行:核心数有限,通信靠共享内存,早期系统更常让一个查询占用一个核心,同时执行许多查询。节点数很多时属于细粒度或大规模并行,数据库会把一次扫描、连接或聚合拆到多个节点执行。后续篇章会深入查询如何拆分;这里先关注这种拆分依赖什么硬件和通信边界。
架构名称描述的是资源关系,不直接等于性能结论。共享内存通信快,却会受内存带宽和一致性流量限制;无共享节点容易横向增加,却要承担远程访问、数据重分布和负载倾斜的代价。
集中式数据库运行在一台计算机系统中。它可以是手机里只供一个应用访问的嵌入式数据库,也可以是一台配有多颗处理器、大量内存和多块存储设备的企业服务器。区别不在用户是否远程连接,而在数据库的处理与持久化是否都落在同一台计算机的资源边界内。
单用户系统很少出现高强度并发更新,因此可能只提供简单的并发控制和恢复能力,有些系统只暴露程序接口而不提供完整 SQL。多用户服务器则要同时处理许多会话,必须有完整的事务隔离、崩溃恢复、访问控制和查询处理能力。一台机器因此也可能承担复杂的企业负载。
操作系统的多任务机制早已迫使数据库处理共享数据结构的并发访问。程序从单处理器迁移到少量共享内存核心时,原有的锁、闩锁和缓冲管理机制仍可沿用。最直接的利用方式是把不同查询分配给不同核心:每个查询未必更快,但单位时间能完成更多查询。
只有把单个查询继续拆成多个并行子任务,才可能缩短该查询的响应时间。这里要区分两个目标:
集中式架构的优势是没有跨节点协议,内存访问和进程协作路径短,部署与恢复边界也清楚。它的上限来自单机可容纳的处理器、内存、I/O 通道和故障风险。当工作集能放入内存、负载增长可预期且单机冗余足够时,集中式系统往往是更容易验证的选择。

图:远程用户可以很多,但数据库仍位于一台计算机内;多个核心通过共享内存并发处理请求。
早期终端几乎只负责输入和显示,全部计算都在中央系统完成。个人计算机普及后,界面、表单校验和部分数据分析可以放到客户端,数据库服务器集中承担查询优化、访问路径、并发控制和恢复。这形成了两层客户端—服务器结构。
面向浏览器和移动端的应用通常再增加应用服务器,构成三层结构:客户端负责交互,应用服务器负责身份验证、业务规则、连接池和接口编排,数据库服务器负责持久化数据和事务。对数据库而言,应用服务器才是直接客户端。这样可以避免每个终端都持有数据库凭据,也能把大量短连接汇聚成受控的数据库会话。

图:三层结构把业务逻辑放在应用服务器,终端不直接越过服务边界访问数据库。
每增加一次网络往返,都可能让本来很快的内存操作变成毫秒级等待。如果一次页面请求先查用户、再查订单、逐条查商品,几十次串行往返会积累成明显延迟。分层设计要配合批量接口、连接复用、预取和缓存,减少“每得到一点信息就再问服务器一次”的聊天式通信。
下面的交互把同一业务请求放到不同层执行。点击职责卡片,可以观察哪些安排会增加数据库暴露面或网络往返。
事务服务器也叫查询服务器。客户端提交 SQL 或专用接口请求,服务器完成解析、优化、执行和事务控制,再返回结果。数据通常留在服务器端,网络上传输的是请求参数与结果集。这是通用数据库最常见的服务器形态。
一个事务服务器往往不是单一进程。它可以为每个会话建立进程,也可以由一个多线程进程服务多个会话,还可以使用多进程与多线程混合结构。无论采用哪种形式,执行单元都要访问共享状态:

图:会话执行单元共享缓冲池、锁表、日志缓冲与计划缓存,后台进程负责落盘、检查点和故障监控。
多个进程修改同一锁表或缓冲区链表时,需要很短的互斥区。处理器提供的“测试并置位”或“比较并交换”原子指令,可以让竞争者中只有一个成功改变某个内存位置。数据库据此实现互斥量或闩锁,保护共享内存结构。
闩锁和事务锁不能混为一谈。闩锁通常只持有几个指令或一次结构修改的时间,解决“内存结构会不会被同时改坏”;事务锁可以跨多条语句持有,解决“两个事务的业务读写能不能同时成立”。原子指令只直接给出排他访问,也不足以替代带共享/排他模式、等待队列和死锁处理的事务锁管理。
为了减少向锁管理进程传递消息的开销,服务器进程可以先取得锁表闩锁,直接检查并更新共享锁表,然后释放闩锁。如果事务锁暂时不能授予,请求进入等待队列;信号量或通知机制让等待事务休眠,避免不停轮询消耗处理器。锁管理进程仍可专门执行全局死锁检测。
共享内存减少了数据复制和消息传递,却把正确性压力转移到同步协议上。闩锁持有过久会把共享结构变成串行瓶颈;没有正确的内存可见性保证,即使代码顺序看似正确,另一核心也可能暂时看到旧值。
事务服务器接收“执行这个动作”的请求;数据服务器接收“读取或更新这个数据项”的请求。数据项可以是元组、对象、文档、文件或文件的一部分。客户端取回数据后执行计算,再把新值写回服务器。这种模式适合客户端计算量很大、服务器主要负责可靠存储的场景,例如模型仿真、设计对象处理或专用数据存储系统。
早期系统曾直接传输数据库页,一个页中可能含有多个数据项。现代数据服务更倾向于暴露逻辑数据项或明确的数据块,避免把内部页布局变成客户端契约。这样服务器可以独立调整存储格式和压缩方式。
本地内存访问通常以纳秒计,而一次网络往返即使在同一数据中心也可能达到微秒到毫秒量级。若事务每读取一个小对象都等待一次往返,时间会主要消耗在等待网络。常见优化包括:

图:缓存命中只有在数据仍有效且访问权仍成立时才能省掉网络往返;冲突出现时服务器要回收锁或使缓存失效。
缓存的难点不是“有没有数据”,而是“这份数据是否仍然有效”。另一个客户端可能已经修改或删除该对象,查询结果还可能因新插入对象而改变。除非业务明确允许陈旧数据,否则客户端仍要验证版本或向服务器取得访问权。
锁缓存需要服务器记录锁被借给了谁。新的冲突请求到达时,服务器先回调持有客户端,要求交回冲突锁;客户端故障会让回收更复杂。粗粒度锁也不是越少越好:它减少消息,却可能把本来互不冲突的数据一起锁住。锁降级通过“取得所需细锁,再释放粗锁”的顺序保持访问连续性;对于缓存中无人使用的对象,可以直接丢弃而不再取得细锁。
设同一个任务在小系统上耗时 ,在资源扩大后的系统上耗时 ,加速比为:
若处理器、磁盘等资源扩大为原来的 倍,执行时间缩短为原来的 ,就得到线性加速。加速比回答的是:“任务不变,多给资源能快多少?”
扩展比把问题规模也放大。让 倍大的系统处理 倍大的任务,若时间仍与原任务在小系统上相同,则实现线性扩展。它回答:“业务与资源同步增长时,服务水平能否保持?”
扩展又分两种。批处理扩展把数据库和长任务的数据规模放大,例如扫描更大的关系;事务扩展同时增加数据库规模和事务到达率,例如账户数扩大十倍,单位时间存取款请求也扩大十倍。数据库容量规划通常更关心扩展比,因为目标常常是承接增长,而不是反复给同一份数据跑得更快。

图:加速保持任务不变;扩展让问题规模和资源同步增加。线性曲线是目标,不是增加机器后的必然结果。
若任务中可并行部分占比为 ,使用 个并行执行单元,理想化执行时间与加速比可写成:
哪怕 ,无限增加执行单元时,加速上限也只有 10。除此之外还有三类常见损耗:启动大量任务需要时间;任务会争用总线、共享磁盘或锁;数据倾斜让最慢子任务决定整体完成时间。十个分片平均工作量为 10,但若一个分片为 20,其余很轻,整体至少要等待这个分片,理想十倍加速就无法实现。
还要同时看绝对性能。一套系统可能扩展曲线漂亮,但起点很慢;另一套系统曲线稍差,却在目标规模下仍更快。架构评估要把目标负载下的响应时间、吞吐量、资源利用率和扩容后变化放在一起。
带宽表示单位时间能搬运多少数据,延迟表示一次消息从发出到到达并返回要等待多久,跳数表示途中经过多少中间节点。批量扫描和数据重分布容易受带宽限制;短事务中的多次依赖请求更怕延迟。只提高链路带宽,无法消除跨地域传播时间,也无法自动减少软件协议栈的处理开销。
并行系统使用过多种互连拓扑:

图:拓扑决定可并发链路、最坏跳数和失效后的替代路径;数据中心通常使用多路径树状网络。
数据中心把服务器装入机架,由机架顶部交换机连接本机架节点,再经汇聚与核心交换机互联。单纯的树在上层容易形成汇聚瓶颈;让每个下层交换机连接多个上层交换机,可以增加可选路径,并在少数链路或交换机故障时绕行。即使如此,跨机架流量仍比机架内通信更稀缺,数据与计算的放置应尽量利用局部性。
常规网络消息会经过发送进程、操作系统、网卡、远端网卡、远端操作系统和接收进程。高性能互连可让应用更直接地访问网络硬件。远程直接内存访问(RDMA)还允许一个节点直接读写另一节点已授权的内存区域,减少显式消息处理和数据复制。
RDMA 改善的是通信路径,不会自动解决并发控制、权限、失效恢复或数据放置。设计者仍要明确远程写入何时可见、失败后如何判断操作结果,以及谁拥有被访问内存的生命周期。
并行数据库最常用的分类依据,是处理器、内存和磁盘之间的共享关系。

图:图中的连线表示资源可见性;层次式架构常在节点内共享内存、节点间采用无共享。
共享磁盘通常借助存储区域网络(SAN),让多个节点像访问本地逻辑磁盘一样访问存储阵列。阵列可以用冗余磁盘和多路径提高可用性。某节点失败时,其他节点仍能看到数据并接管工作,适合并行度不极端但重视快速接管的场景。它的问题是所有 I/O 都要经过存储网络,带宽和缓存协调可能成为瓶颈。
无共享架构让每个节点服务自己拥有的数据,避免所有 I/O 汇聚到单一存储互连。网络容量可以随节点数增长,因此能扩到大量节点。代价是远程数据必须经过两端软件和网络,分区键不合适时会产生大量跨节点访问;热点或数据倾斜还会让少数节点先达到上限。
现实系统多为层次式:一台节点内部有多个共享内存核心,多个节点之间不共享内存和本地磁盘。这样既利用节点内低延迟,又用节点间无共享获得规模。架构决策不应强迫整套系统只选一个标签,而要逐层标出资源关系。
早期共享内存系统让处理器通过公共总线访问所有内存。处理器增加后,总线一次只能服务有限通信,核心会把时间花在等待内存。现代服务器常把一组内存直接连接到某颗处理器,同时允许其他处理器经高速互连访问。这种非一致内存访问(NUMA)结构仍提供统一地址空间,但本地内存比远端内存更快。
数据库若忽略 NUMA,把执行线程安排在一个处理器上、缓冲页却长期分配在另一处理器旁,远端内存流量会吞掉并行收益。实际优化会让线程、内存页与 I/O 尽量保持局部,并避免所有工作线程争用同一个共享计数器或队列。
缓存进一步放大了“位置”差异。每个核心通常有很小很快的 L1 缓存,再有较大的 L2;多个核心还可能共享 L3。主内存访问比缓存慢得多,缓存未命中会让核心等待。硬件线程可以在一个逻辑线程等待时执行另一个逻辑线程,但它不能增加物理核心的实际执行资源,也无法消除内存带宽上限。
核心 A 更新某个内存位置后,核心 B 的缓存中可能仍有旧副本。硬件缓存一致性协议以缓存行为单位跟踪“已修改、独占、共享、无效”等状态,并向其他缓存发送失效信息。为提高性能,这些消息可能延迟到达或延迟处理,程序不能仅凭源码中的先后顺序推断另一核心已经看见更新。
内存屏障约束读写在屏障前后的可见顺序。数据库开发者通常不直接在每处业务代码里写屏障,而是通过正确的互斥量、闩锁和语言同步原语获得这些保证:释放锁前确保写入向外可见,取得锁后再读取最新状态。事务锁解决数据库对象的并发语义,缓存一致性和内存屏障解决处理器如何观察共享内存,两层机制处于不同抽象层。
增加核心后性能停滞,不一定是 SQL 无法并行。先查看缓存未命中、远端 NUMA 访问、内存带宽和共享闩锁等待,才能判断瓶颈在执行计划还是硬件资源关系。
无共享并行数据库和分布式数据库都由独立节点组成,也都通过网络通信。关键区别在距离、网络性质、节点异质性与管理边界。并行节点通常位于同一数据中心,硬件相近并由同一系统统一管理;分布式站点可能跨城市或国家,链路延迟更高、带宽更稀缺,站点可运行不同软件并保留不同程度的自治。
一个事务只访问发起站点的数据时是本地事务;访问其他站点或多个站点时是全局事务。全局事务的每一次依赖通信都受到广域网延迟影响,因此不能照搬单机中频繁交互的写法。数据应尽量靠近主要读者,跨地域协议要减少串行往返。
广域网链路可能失效,使两个仍在运行的站点暂时无法互相通信,这叫网络分区。此时系统既无法简单断定对方已经崩溃,也可能无法同时保证所有站点立即可用且看到完全一致的数据。跨地域架构必须预先规定哪些操作可以继续、哪些必须等待,以及恢复通信后如何合并或纠正状态。
单个节点冗余也不足以抵御机房级灾害。火灾、供电中断或自然灾害可能同时影响一个数据中心的大量节点,因此高可用系统会把副本放到地理隔离的站点。这样做增加了传播延迟、合规和一致性成本,不能只把“多一份副本”当成免费保险。
由现有数据库连接形成的系统还分为同构与异构。共同使用全局模式和相同管理软件、主动协作的站点属于同构分布式数据库;不同站点保留自己的模式与软件,只提供有限协作时,更接近联邦式或异构数据库。后续分布式主题会继续讨论数据放置、查询和事务协议,本节只建立架构边界。
自建环境中,组织购买服务器并维护机房、电力、散热、硬件、操作系统、数据库和应用。云服务把其中一部分责任交给服务提供方,并通过大型资源池按需分配能力。三类服务模型的区别,可以沿技术栈从下到上理解:
数据库即服务属于平台能力:客户端得到查询、事务和管理接口,而不只是一块保存字节的存储。云数据存储服务可能只提供文件、对象或键值访问,不一定提供模式、SQL 和完整事务。选择时要确认接口语义,不能把“数据能保存”误当成“数据库能力相同”。
虚拟机在一台物理服务器上模拟多台独立计算机,每台虚拟机运行自己的操作系统,隔离清楚但开销较高。容器共享宿主操作系统内核,为应用提供独立网络地址、库和文件系统视图,启动更快、密度更高,适合把应用拆成多个通过网络接口协作的服务。
弹性表示短时间增加或释放计算、存储实例的能力。它改善的是供给速度,不保证数据库立刻获得线性扩展。新节点加入后,数据是否已分布到位、热点是否仍集中、连接是否均衡、状态服务能否横向拆分,都会影响真正的容量收益。
云服务减少前期硬件投入和机房维护,也让临时高峰更容易得到资源。代价是数据由另一组织托管,安全控制、法律责任、数据驻留地和跨区费用都要纳入设计。即使提供方负责平台运行,使用方仍要为账户权限、数据分类、恢复目标和业务正确性负责。
一个可复核的架构决策可以按以下顺序完成:
先描述工作负载。记录事务到达率、查询响应时间目标、数据规模、增长速度、读写比例、热点分布和批处理窗口,不用“高并发”“海量数据”代替数字。
再画出数据与请求路径。标出客户端、应用服务器、数据库执行节点、内存、存储和副本,统计关键操作的网络往返、跨节点数据量与必须同步等待的环节。
明确故障模型。分别考虑进程、机器、磁盘、机架、链路和整个站点失效,写清楚恢复时间目标、可接受的数据丢失范围,以及网络分区时哪些操作宁可暂停。
用目标规模压测候选架构。除了平均吞吐量,还要看尾延迟、最忙节点、锁与闩锁等待、内存带宽、存储队列、跨机架流量和数据倾斜。
一套部门级事务系统,数据量可装入单机内存且停机窗口明确,通常先从冗余存储的集中式服务器起步。需要多节点快速接管同一数据、并行度中等时,可以评估共享磁盘集群。数据量持续扩大、查询能按分区并行且团队能管理数据分布时,无共享或层次式架构更有扩展空间。用户跨地域且整站失效也要继续服务时,才需要把副本、网络分区和地域法规一起纳入分布式设计。
架构应跟着可观测瓶颈演进。若当前限制只是慢 SQL 或错误索引,增加节点会把同样的低效复制到更多机器;若限制来自共享存储带宽,就要调整数据与 I/O 关系;若限制来自跨地域串行往返,就要改变接口和数据位置。最终交付物不是一张“先进架构”示意图,而是一组可以被压测、故障演练和容量数据证伪的假设。
判断架构是否合适,可以回到一个朴素标准:在目标负载和约定故障下,系统能否用可承担的成本稳定满足响应时间、吞吐量、恢复与数据正确性要求。
最后核对责任边界与迁移成本。确认谁负责备份、升级、密钥、容量和故障演练,并验证数据能否以可接受的时间和费用迁出。