数据库为何以及如何使用单个文件存储所有数据?

时间:2008-12-02 02:05:02

标签: database

我遇到的许多数据库(如SQL Server)使用单个文件来存储整个数据库。这似乎是一种非常常见的方法。将整个数据库存储在单个文件中有什么好处,而不是将数据分解为更多逻辑单元,例如每个文件一个表。

此外,数据库如何在内部工作。它如何处理不同线程对同一文件的并发写入。在大多数应用程序中,我看到你一次只能在一个文件上有一个打开的写入句柄。各种数据库引擎如何处理并发写入。

4 个答案:

答案 0 :(得分:22)

服务器应用程序可以处理单个非碎片大文件,就像操作系统处理原始磁盘一样:可随机搜索的字节块。如果选择使用数据库服务器,则可以在该字节块之上实现整个文件系统,如果将表实现为单独的文件有好处。

同时写入同一文件的不同部分不是问题。数据库使用锁定策略来确保多个线程不会尝试访问文件的同一部分,这是数据库事务存在的主要原因之一:隔离一个事务与另一个事务的可见影响。

例如,数据库服务器可能会跟踪哪些表在哪些行中被哪些正在进行的事务访问;当事务退出时,它所触及的行被释放,以便其他事务可以自由访问它们。在这种情况下,其他事务可能只是阻止 - 即等待 - 当他们尝试访问当前属于另一个事务的行时。如果另一个事务未在合理(可配置)时间内完成,则等待事务可能会中止。通常造成这种情况的原因是僵局。然后,使用数据库的应用程序可以选择(如果需要)重试该事务。

这种锁定可以使用信号量或其他同步机制来实现,具体取决于性能权衡。

答案 1 :(得分:6)

是的,给定文件可能只有一个带有打开文件描述符的进程,否则不同进程可能会覆盖彼此的工作。通常,数据库上的所有I / O都必须由RDBMS进程完成。然后,所有应用程序通过一些进程间通信(包括网络)提交查询,并获得结果。因此,数据库文件的物理I / O是集中的。

在实践中,RDBMS实现通常还有一个锁定管理器线程来管理对表,页面或行的子部分的访问,这取决于RDBMS实现。这会产生“瓶颈”,因为虽然RDBMS可能有许多线程执行查询并进行网络通信,但是对数据库的给定部分的并发访问仍然必须排队以获取锁。将锁管理完全并行是非常棘手的。

对于单个文件与多个文件,优缺点还取决于RDBMS实现。一个例子是MySQL的InnoDB,它默认使用单文件方法。但如果删除一堆数据,它不知道如何缩小文件;它只是将文件中的一些空格标记为“空闲”,以供后续插入使用。即使您删除整个表,该文件也不会缩小。但是,如果在设置InnoDB表空间时选择了file-per-table选项,并且删除了表,InnoDB可以删除该表的文件,从而释放磁盘空间。

答案 2 :(得分:4)

我认为巴里的答案非常好。我只想说几点想法。请注意文件系统和原始设备之间的这种模糊,这是完全不同的,但在概念上可以认为是相同的。

为什么DBMS供应商会推出自己的I / O管理等。

<强>控制

当大多数DBMS系统成长时(Oracle,DB2,Sybase ASE {SQL Server是Sybase ASE的表兄}})操作系统的文件系统不像现在那样先进,但进展迅速(Oracle于1979年编写) !!,Sybase,1987年)。假设操作系统可以做各种既快速又安全的花哨的东西并不总是给定的。 DBMS供应商编写了自己的I / O库,以帮助降低他们不会受到操作系统怪癖影响的可能性,或者随着技术的发展而变得过时。

现在这种情况不那么普遍了(MySQL,PostgreSQL,SQLite等都不这样做) - 甚至SQL Server也将很大一部分管理转回到Windows,因为Windows团队与SQL Server团队密切合作优化DBMS工作负载。

安全

严格控制整个数据文件允许DBMS确保在需要时进行写入,而不是在操作系统感觉到时进行写入。保留自己的数据缓存可确保操作系统不会认为某些低级日志轮换作业会将重要的数据库数据分页。

<强>一致性

Oracle,Sybase ASE等非常复杂的非常昂贵的系统。如果您在DBMS安装上花费了1000万美元并且运行缓慢(或者更糟糕的是,数据损坏了!),因为您的操作系统内核的特定版本中存在一些疯狂的错误,您会责怪谁? DBMS供应商。滚动您自己的I / O,锁定管理,并发控制,线程等当然是很难做到的 - 但是当您绝对需要DBMS跨越各种操作系统的可重复,一致的行为时,您必须采取操作系统尽可能地脱离等式。

同样,随着操作系统的成熟和发展,许多新系统都试图尽可能地使用操作系统级别的功能,但即便是MySQL也有一些可以在my.cnf中配置的缓冲池

答案 3 :(得分:0)

相关说明。 我相信MSFT建议您为系统表创建一个文件组,为其他对象创建一个文件组。还可以创建另一个来存储索引。我们不这样做,因为我们的应用程序都不需要如此高的性能。这也会增加维护的复杂性。