Bitcointalk · RFC: ship block chain 1-74000 with release tarballs?

中本聪,2010 年 11 月 29 日

SN-3684 已核对来源,附原文与上下文。

阅读语言
中文译文

看起来你倾向于把一切都假设成错的,比实际情况还要过头。

写区块索引是轻量工作。构建交易索引才是每个区块都要做更多随机访问的。我怀疑慢就慢在读取所有前序交易输入上。读缓存对此会有帮助。最好由 DB 来做。兴许它有设置缓存内存大小的选项。

1) 比特币理应在程序启动时就打开数据库而不仅仅是环境,并在程序关闭时关闭数据库。

它已然这么做了。见 CDB。(譬如)CTxDB 对象的生命周期不过是为了支持数据库事务,以及关闭时判断数据库是否还有人在用。

而且,比特币还强制做一次数据库检查点,把日志里的全部事务推进主数据库。

倘若它真在那么做,会慢得多。它本该不过是一分钟一次或 500 区块一次:

if (strFile == "blkindex.dat" && IsInitialBlockDownload() && nBestHeight % 500 != 0)
        nMinutes = 1;
    dbenv.txn_checkpoint(0, nMinutes, 0);

或许理应加上这个: if (!fReadOnly) dbenv.txn_checkpoint(0, nMinutes, 0);

2) 对于初始区块下载,事务提交理应每 N 条记录发生一次,而不是每条记录一次。我建议 N=1000。

事务提交意味着刷盘吗?这让我很意外。我以为包在事务里的数据库操作会像其他数据库操作一样被记日志。很多数据库应用几乎每一对操作都得包进事务,譬如把钱从一个账户挪到另一个。(借记 a,贷记 b)我无法想象它们还被要求自己把操作攒成批。

在下面两种情况下,情况 1 刷一次盘、情况 2 刷两次吗?

情况 1: write write write write checkpoint

情况 2: begin transaction write write commit transaction begin transaction write write commit transaction checkpoint

扭曲我们的数据库用法不会是正确的路子。出路在于 BDB 设置和缓存。

ORIGINAL · 英文原文
It seems like you're inclined to assume everything is wrong more than is actually so.

Writing the block index is light work.  Building the tx index is much more random access per block.  I suspect reading all the prev txins is what's slow.  Read caching would help that.  It's best if the DB does that.  Maybe it has a setting for how much cache memory to use.

Quote
1) bitcoin should be opening databases, not just environment, at program startup, and closing database at program shutdown.
Already does that.  See CDB.  The lifetime of the (for instance) CTxDB object is only to support database transactions and to know if anything is still using the database at shutdown.

Quote
And, additionally, bitcoin forces a database checkpoint, pushing all transactions from log into main database.
If it was doing that it would be much slower.  It's supposed to be only once a minute or 500 blocks:

    if (strFile == "blkindex.dat" && IsInitialBlockDownload() && nBestHeight % 500 != 0)
        nMinutes = 1;
    dbenv.txn_checkpoint(0, nMinutes, 0);

Probably should add this:
    if (!fReadOnly)
        dbenv.txn_checkpoint(0, nMinutes, 0);

Quote
2) For the initial block download, txn commit should occur once every N records, not every record.  I suggest N=1000.
Does transaction commit imply flush?  That seems surprising to me.  I assume a database op wrapped in a transaction would be logged like any other database op.  Many database applications need to wrap almost every pair of ops in a transaction, such as moving money from one account to another. (debit a, credit b)  I can't imagine they're required to batch all their stuff up themselves.

In the following cases, would case 1 flush once and case 2 flush twice?

case 1:
write
write
write
write
checkpoint

case 2:
begin transaction
write
write
commit transaction
begin transaction
write
write
commit transaction
checkpoint

Contorting our database usage will not be the right approach.  It's going to be BDB settings and caching.
来源
Bitcointalk 原始链接 ↗ 记录编号 SN-3684