很多现代的操作系统都会提供基于软件的 RAID 实现,一些云服务厂商也会使用自研的文件系统或者冗余备份机制:
- Google 使用 Google 文件系统管理文件,它以块的方式存储文件并且通过主服务管理所有的文件块[^8];
- Microsoft 在 Azure 中使用擦除编码的方式计算冗余数据[^9];
实现复杂
数据库管理系统最终会将数据存储在磁盘上,对于很多数据库来说,数据落到磁盘上就意味着持久化完成了 。磁盘作为数据库系统的下层,磁盘能够稳定存储数据是数据库能够持久化数据的基础 。
文章插图
database-and-disk
图 3 - 数据库依赖磁盘
很多人都误认为使用 write就能将数据写入到磁盘上,然而这是错误的 。函数 write不仅不能保证数据写入磁盘,有的实现甚至都不能保证目标空间保留给了写入的数据[^10] 。一般情况下,对文件的 write只会更新内存中的页缓存,这些页缓存不会立刻刷入磁盘,操作系统的 flusher 内核线程会在满足以下条件时将数据落盘[^11]:
- 空闲内存下降到了特定的阈值,需要释放脏页占用的内存空间;
- 脏数据持续了一定时间,最老的数据就会被写入磁盘;
- 用户进程执行 sync或者 fsync系统调用;
文章插图
write-and-fsyn
图 4 - 写入和落盘
write和 fsync在数据库管理系统中非常重要,它们是提供持久性保证的核心方法,一些开发者对 write的理解错误写出错误的代码就会导致数据丢失 。
除了持久化的特性之外,数据库可能还需要提供 ACID(Atomicity, Consistency, Isolation, Durability)或者 BASE(Basically Available, Soft state, Eventual consistency)的保证,有些数据库还会提供分片、副本以及分布式事务等复杂功能,这些功能的引入也增加了数据库系统的复杂性,而随着程序复杂性的增加,出现问题的可能性也随之增长 。
总结
数据库管理系统是软件工程中最复杂、最重要的系统之一,几乎所有服务的正常运行都建立在数据库不会丢失数据的假设上 。然而因为如下所示的原因,数据库不能完全保证数据的安全:
- 运维人员在配置和运维时极有可能因为操作失误导致数据丢失;
- 数据库依赖的底层磁盘发生硬件错误,导致数据无法恢复;
- 数据库系统支持的功能非常多而且复杂,数据没有及时落盘就可能造成数据丢失;
- 除了文中列出的数据丢失事故,还有哪些数据库或者云服务商丢失过数据?
- redis 的 RDB 和 AOF 机制什么时候会将数据落盘?
- 数据成功写入数据库究竟应该如何定义?
如果对文章中的内容有疑问或者想要了解更多软件工程上一些设计决策背后的原因,可以在博客下面留言,作者会及时回复本文相关的疑问并选择其中合适的主题作为后续的内容 。[^1]: Brandur. May 7, 2017. "The long road to Mongo's durability" https://brandur.org/fragments/mongo-durability
[^2]: Huachao HUANG. Fri, Sep 8, 2017. "How We Found a Data Corruption Bug in RocksDB" https://pingcap.com/blog/2017-09-08-rocksdbbug/
[^3]: 腾讯云. Aug, 2018. 关于客户“前沿数控”数据完整性受损的技术复盘 https://mp.weixin.qq.com/s/8JSPY6vHPhg8pX0JwjqttQ
[^4]: Draven. Dec, 2019. "为什么基础服务不应该高可用 · Why's THE Design?" https://draveness.me/whys-the-design-unstable-infrastructure
推荐阅读
- Redis为什么是单线程,高并发快由哪些因素决定?
- 黑茶银耳饮会反弹吗,孕妇可以喝菊花茶吗
- 百度截流怎么做?百度截流百度霸屏技术教程,看完本文即可学会百度霸屏技术
- PHP初学者总会遇到非常头疼问题,今天给你们总结一下
- 报销|为什么很多公司面试不报销路费?
- 发动机为什么要大修?家用车做好这3点,开到报废也不用大修
- 地球绕太阳的公转为什么是椭圆轨道?
- C1增加D证需要多久,会很难吗
- 人在单位,面对以下几个规则,你要学会变通
- 聪明的员工,在辞职前都会懂得做这4点