我遇到的许多数据库(如SQL Server)使用单个文件来存储整个数据库.这似乎是一种非常常见的方法.将整个数据库存储在单个文件中有什么好处,而不是将数据分解为更多逻辑单元,例如每个文件一个表.
此外,数据库如何在内部工作.它如何处理不同线程对同一文件的并发写入.在大多数应用程序中,我看到你一次只能在一个文件上有一个打开的写入句柄.各种数据库引擎如何处理并发写入.
服务器应用程序可以处理单个非碎片大文件,就像操作系统处理原始磁盘一样:可随机搜索的字节块.如果选择使用数据库服务器,则可以在该字节块之上实现整个文件系统,如果将表实现为单独文件有好处的话.
并发写入同一文件的不同部分不是问题.数据库使用锁定策略来确保多个线程不会尝试访问文件的同一部分,这是数据库事务存在的主要原因之一:隔离一个事务与另一个事务的可见影响.
例如,数据库服务器可能会跟踪哪些表在哪些行中被哪些正在进行的事务访问; 当事务退出时,它所触及的行被释放,以便其他事务可以自由访问它们.在这种情况下,其他事务可能只是阻止 - 即等待 - 当他们尝试访问当前属于另一个事务的行时.如果另一个事务未在合理(可配置)时间内完成,则等待事务可能会中止.通常造成这种情况的原因是僵局.然后,使用数据库的应用程序可以选择(如果需要)重试该事务.
可以使用信号量或其他同步机制来实现此锁定,这取决于性能权衡.
是的,给定文件可能只有一个进程具有打开的文件描述符,否则不同的进程可能会覆盖彼此的工作.通常,数据库上的所有I/O都必须由RDBMS进程完成.然后,所有应用程序通过一些进程间通信(包括网络)提交查询,并获得结果.因此,数据库文件的物理I/O是集中的.
在实践中,RDBMS实现通常还有一个锁定管理器线程来管理对表,页面或行的子部分的访问,这取决于RDBMS实现.这会产生"瓶颈",因为虽然RDBMS可能有许多线程执行查询并进行网络通信,但是对数据库的给定部分的并发访问仍然必须排队以获取锁.使锁管理完全并行是非常棘手的.
对于单个文件与多个文件,优缺点还取决于RDBMS实现.一个例子是MySQL的InnoDB,它默认使用单文件方法.但如果删除一堆数据,它不知道如何缩小文件; 它只是将文件中的一些空格标记为"空闲",以供后续插入使用.即使您删除整个表,该文件也不会缩小.但是,如果在设置InnoDB表空间时选择了file-per-table选项,并且删除了表,InnoDB可以删除该表的文件,从而释放磁盘空间.