高频金融系统如何防止突然断电导致的数据丢失?

145 天前
 latifrons

我知道 MySQL ,RocksDB 等数据库其实都有 WAL ,但同样地都依赖操作系统定期将内存缓存中的数据通过 fsync()刷回磁盘。如果此时断电(或者操作系统崩溃),1 秒内的数据可能会丢失。

MySQL:innodb_flush_log_at_trx_commit

https://dba.stackexchange.com/questions/12611/is-it-safe-to-use-innodb-flush-log-at-trx-commit-2

The default value of 1 is required for full ACID compliance. You can achieve better performance by setting the value different from 1, but then you can lose up to one second worth of transactions in a crash. With a value of 0, any mysqld process crash can erase the last second of transactions. With a value of 2, only an operating system crash or a power outage can erase the last second of transactions. InnoDB's crash recovery works regardless of the value.

所以似乎为了数据完备性,innodb_flush_log_at_trx_commit=1 是不可避免的,从而会导致比较严重的性能劣势。

例如 LevelDB ,开启 WriteOptions(Sync=true)后,tps 从 190000/s 骤降为 1200/s.

Qwen3 的一个回答: https://chat.qwen.ai/s/0e7d9977-4400-41da-883f-2972893104cf?fev=0.0.85

想请教一下大家,在对数据完备性要求极高的场景下,大家是怎么优化性能的?

11047 次点击
所在节点    程序员
133 条回复
wxf666
141 天前
@scegg 就算磁盘保证实际写入一定完成,也不能解决楼主《提交事务后,每秒落盘前,数据库/系统崩溃,数据丢失》问题吧。。

还是得在 commit 里,落盘数据,再结束事务。。

但每次 commit 都落盘数据,不划算,最好攒个几百事务平摊成本。。( 4K 顺序写,慢于,1M 顺序写)

数据库有提供此种机制吗?
julyclyde
141 天前
@wxf666 数据库的事务日志就是这样的
v1
141 天前
@julyclyde 怎么每次你都能把不懂装懂演绎到极致?而且究极嘴硬。
julyclyde
140 天前
@kk2syc 不懂的是你吧
starinmars
140 天前
在线式 ups 加柴油发动机自启
scegg
140 天前
wxf666
140 天前
@julyclyde #102 数据库的事务日志。。是啥样的? commit 后,每秒刷新落盘到磁盘上?

那还是解决不了楼主说的《 commit 后,落盘前,数据库/系统崩溃,数据丢失》呀。。



@scegg #106 《要求事务完全持久化》肯定是数据库基础功能。连几百 KB 的 SQLite ,甚至在 20 年前都做到了。。( PRAGMA synchronous = FULL )

关键是数据库有没有采取措施,既保证《完全持久化》,又降低每个事务的持久化时间。。

每次 commit 都落盘,会很慢。积攒一堆事务再落盘,可以平摊成本。

但 sqlserver 文档里没看到类似方法及配置选项?(如:最长等待 0.1 秒就落盘现存事务;最多积攒 1000 个事务 / 1MB 数据页就落盘;……)
v1
140 天前
公开信息里面最好的参考就是微众银行,用的自研 TDSQL 。

在文档的“强同步”部分说明了( https://cloud.tencent.com/document/product/557/10570 ),只有当备机数据完全同步(日志)后,才由主机给予应用事务应答,保障数据正确安全。

julyclyde
140 天前
@wxf666 我没说解决啊
我说“数据库的事物日志是这样的”回复的是“攒个几百事务平摊成本”

想解决的话,你自己也知道方法啊,就是不攒,每个都写入
放弃性能什么都好说
scegg
140 天前
@wxf666 数据库没有办法满足既要又要的功能,只能允许使用者自己做出取舍。既要又要这种需求只能存在在无法实现的文件里。
wxf666
139 天前
@julyclyde #109 你说的是《 commit 后,攒几百再落盘》吧

我意思是,数据库应该提供《 commit 时,等待积攒一批事务,再落盘,最后才结束事务》特性,既《确保数据完全持久化》,又《平摊落盘成本,尽可能降低每事务延迟》的。。



@scegg #110 提供上一行的功能,会有啥问题吗?

sql server 不也允许《不同事务有不同持久性:完全持久( commit 时,积攒一个落盘一次)、延迟持久( commit 后,积攒一堆落盘一次)》吗?

再多加一个《延迟完全持久( commit 时,积攒一堆落盘一次)》不算过分吧。。

特别地,《延迟完全持久》配置为《最多积攒一个》或《最多等待 0 秒》,就退化成《完全持久》了。。

感觉没啥问题呀。。
OC0311
139 天前
真出现了 就使用上一次快照信息,直接回滚数据再重放消息处理。
julyclyde
139 天前
@wxf666 攒几百是你说的。我是回复给你
你如果选择了攒几百,那必然会丢数据;每个都写盘,那必然性能差
这都是没什么可讨论的事了
wxf666
139 天前
@julyclyde #113 请教一下,为啥会丢数据呢?(攒几百事务落盘,再结束这几百个 commit / 事务)

还是说《用户只要发了交易请求,就算处理过程中数据库 / 系统崩溃,服务器也必须处理成功!不接受 rollback !即使是可串行化级别事务也不行!》?

用户为啥不能接受《交易失败,您的资金一切正常,请稍后重试》呢。。

scegg
139 天前
@wxf666 积攒提交在数据库服务器上意义不大。
首先,数据库是随机操作,积攒落盘也只是要批量执行这一些写入操作,并不一定会减少写入次数。
然后,数据库后端通常都是 HBA 连接的 LUN ,它自己就有自己的写入队列、写入日志、写入缓存、分层存储等多个策略在排队,并不需要数据库替他们操心。
stone981023655
138 天前
金融银行都有 UPS+发电机的, 停电了发电机就在工作了, 完全不虚。
Litccc
138 天前
楼主说的是软件层面的吧,金融行业的数据中心硬件层面有双路市电+UPS+柴发,断电造成数据丢失基本不可能
julyclyde
138 天前
@wxf666 想要攒够再存盘,结果还没存上就断电了,于是就丢了呗。攒的越多,风险越大啊
不只 redo log 可以合并,连 page 的写盘动作也是可以合并的

发展了这么多年,并没有从理论上突破这个限制,只是在工程实践上有所改善而已
Kazetachinu
137 天前
@stone981023655 #116 可能他说的不是高压侧,而是末端的设备突然自己断电,跟高压无关。现在的高压基本上都稳定的了,这种用电在高压设计中,至少都是双回路和高可靠专线接入,还有发电机和 ups ,除非上级变电站全部跳闸失压,要么地球爆炸,不然没有高压断电风险的。
wxf666
137 天前
@scegg #115

1. 不追求一定要减少随机写入次数呀?关键是想利用顺序写入,快速完全持久化一批事务数据,减少交易事务延迟?(毕竟是落盘才结束事务)

2. 你是说,fsync 能又快又安全落盘到 LUN 写入队列/日志/缓存/分层/…,所以即使 commit 一次就落盘一次,延迟也能很低,并发量也能很大,系统崩溃断电 数据也能很安全,进而解决楼主的问题了?



@julyclyde #118

1. 丢就丢了呗,反正事务没提交成功(因为是攒一批事务,再一起完全落盘提交,事务才结束),又不会对后续其他交易事务有啥影响(比如一钱多用),提示用户《交易失败,服务器忙,资金不变,稍后重试》就行了?

2. 就算不攒事务,commit 一次落盘一次,高频系统每秒钟照样还有几千上万笔交易事务在处理呀?系统崩溃 / 断电,这些处理中事务照样失败,这批用户交易请求数据照样丢失,照样需要提示用户《交易失败,稍后重试》?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1128883

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX