youjiali1995 / youjiali1995.github.io

https://youjiali1995.github.io/
MIT License
8 stars 4 forks source link

storage/boltdb/ #4

Open utterances-bot opened 2 years ago

utterances-bot commented 2 years ago

boltdb 源码分析 - 我叫尤加利

介绍 boltdb 的设计与实现。

https://youjiali1995.github.io/storage/boltdb/

lujiahaoo commented 2 years ago

写的好啊哥哥!

lujiahaoo commented 2 years ago

你好,想请教一下boltdb在提交事务的时候是先将freelist刷盘,然后是page,最后是meta。

if err := tx.db.freelist.write(p); err != nil {
        tx.rollback()
        return err
    }
...

// Write dirty pages to disk.
    startTime = time.Now()
    if err := tx.write(); err != nil {
        tx.rollback()
        return err
    }
...

// Write meta to disk.
    if err := tx.writeMeta(); err != nil {
        tx.rollback()
        return err
    }

假如在page之后、meta之前断电了,下次boltdb重启初始化时是如何知道freelist、page是否已经发生过变更而meta未更新的情况?

我在Open中只看到了对meta进行checksum的操作。。 。

skyitachi commented 2 years ago

freelist和page都是写到新的page里面,原来的page是不会变的,meta更新失败相当于还是原来那棵B树

francisLee777 commented 2 years ago

实测一楼老哥的问题,写数据并打断点测试。 page 写盘之后确实是在db文件里有,但 meta 没写成功的话,下一次重启的时候,相关的读取逻辑读不到刚才写的page,而且之后再commit会把刚才的page覆盖掉! 所以 meta 页没写成功的话相当于”逻辑上“kv数据没写成功。

jackysp commented 2 years ago

赞!

shadow150519 commented 2 years ago

里面提到的page结构体就对应了一个文件系统中的page是不是有点问题,应该是对应一个或多个吧?

jash16 commented 2 years ago

// freePages releases any pages associated with closed read-only transactions. func (db *DB) freePages() { // Free all pending pages prior to earliest open transaction. sort.Sort(txsById(db.txs)) minid := txid(0xFFFFFFFFFFFFFFFF) if len(db.txs) > 0 { minid = db.txs[0].meta.txid //=1 } if minid > 0 { db.freelist.release(minid - 1) }

// Release unused txid extents.
for _, t := range db.txs {
    db.freelist.releaseRange(minid, t.meta.txid-1)
    minid = t.meta.txid + 1
}
db.freelist.releaseRange(minid, txid(0xFFFFFFFFFFFFFFFF))
// Any page both allocated and freed in an extent is safe to release.

}

这段代码中, // Release unused txid extents. for _, t := range db.txs { db.freelist.releaseRange(minid, t.meta.txid-1) minid = t.meta.txid + 1 } 这里会不会说,比如读事务id 590 还在 ,确要释放591~592的写事务涉及到的page; 写事务591涉及到的page会不会影响到读事务590呢?

fy0 commented 1 year ago

遇到了几次掉电之后数据库损坏,难受…… 不知道BadgerDB会不会更好,那个有WAL

Akiqqqqqqq commented 8 months ago

请教一下,第一段说“支持事务(ACID),使用 MVCC 和 COW,允许多个读事务和一个写事务并发执行,但是读事务有可能会阻塞写事务,适合读多写少的场景。”

但是问GPT4 boltdb是否有mvcc 后,回答如下:

BoltDB 不支持多版本并发控制(MVCC)。MVCC 是一种数据库技术,允许多个事务同时访问同一数据的不同版本,从而提高并发性能,特别是在有大量读取操作的时候。MVCC 通过为每个读取事务创建数据的快照来工作,使得读取事务可以访问数据的一致状态,而不会被其他并发写入事务所影响。

BoltDB 实现了一种简化的事务模型,支持多个只读事务并发执行,但它们都会看到写入事务开始时数据库的状态。写入事务在 BoltDB 中是串行执行的,这意味着在任何给定时间只能有一个写入事务在进行。这种设计简化了 BoltDB 的实现,但它意味着 BoltDB 不能提供 MVCC 那样的高级并发控制。因此,BoltDB 适合于读多写少的应用场景,其中读操作可以安全地并发执行,而写操作则需要排队执行。

并且使用boltdb的etcd也是线路mvcc。请问论述是否有误?

youjiali1995 commented 8 months ago

@Akiqqqqqqq 可以看看 https://youjiali1995.github.io/database/CMU-15445/ 里对 boltdb 的补充,之前(这篇博客)的理解有些偏差。

loveRhythm1990 commented 5 months ago

pos // key 距离 leafPageElement 的位移 有大佬能帮忙解释下 pos 是怎么算出来的吗?为什么我看所有 element 的 pos都是一个位置