Skip to content

Commit

Permalink
use defer foreign keys for migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
n8maninger committed Mar 27, 2024
1 parent 0161063 commit 8795e00
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 11 deletions.
96 changes: 96 additions & 0 deletions persist/sqlite/blocks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package sqlite

import (
"path/filepath"
"testing"
"time"

"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
"go.sia.tech/fsd/renterd"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
"lukechampine.com/frand"
)

func TestBlockLocation(t *testing.T) {
log := zaptest.NewLogger(t)
db, err := OpenDatabase(filepath.Join(t.TempDir(), "fsd.sqlite3"), log.Named("sqlite3"))
if err != nil {
t.Fatal(err)
}
defer db.Close()

var cids []cid.Cid
for i := 0; i < 10000; i++ {
mh, err := multihash.Encode(frand.Bytes(32), multihash.SHA2_256)
if err != nil {
t.Fatal(err)
}

c := cid.NewCidV0(mh)
c = cid.NewCidV1(c.Type(), c.Hash())
err = db.Pin(renterd.PinnedBlock{
Cid: c,
Bucket: "test",
ObjectKey: c.String(),
})
if err != nil {
t.Fatal(err)
}
cids = append(cids, c)
}

c := cids[frand.Intn(len(cids))]
start := time.Now()
bucket, key, err := db.BlockLocation(c)
elapsed := time.Since(start)
if err != nil {
t.Fatal(err)
} else if bucket != "test" || key != c.String() {
t.Fatalf("unexpected result: %v %v", bucket, key)
}
log.Debug("block location", zap.Stringer("cid", c), zap.String("bucket", bucket), zap.String("key", key), zap.Duration("elapsed", elapsed))
}

func BenchmarkBlockLocation(b *testing.B) {
log := zaptest.NewLogger(b)
db, err := OpenDatabase(filepath.Join(b.TempDir(), "fsd.sqlite3"), log.Named("sqlite3"))
if err != nil {
b.Fatal(err)
}
defer db.Close()

var cids []cid.Cid
for i := 0; i < 10000; i++ {
mh, err := multihash.Encode(frand.Bytes(32), multihash.SHA2_256)
if err != nil {
b.Fatal(err)
}

c := cid.NewCidV0(mh)
c = cid.NewCidV1(c.Type(), c.Hash())
err = db.Pin(renterd.PinnedBlock{
Cid: c,
Bucket: "test",
ObjectKey: c.String(),
})
if err != nil {
b.Fatal(err)
}
cids = append(cids, c)
}

b.ResetTimer()
b.ReportAllocs()

for i := 0; i < b.N; i++ {
c := cids[i%len(cids)]
bucket, key, err := db.BlockLocation(c)
if err != nil {
b.Fatal(err)
} else if bucket != "test" || key != c.String() {
b.Fatalf("unexpected result: %v %v", bucket, key)
}
}
}
15 changes: 4 additions & 11 deletions persist/sqlite/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,11 @@ func (s *Store) upgradeDatabase(current, target int64) error {
log := s.log.Named("migrations")
log.Info("migrating database", zap.Int64("current", current), zap.Int64("target", target))

// disable foreign key constraints during migration
if _, err := s.db.Exec("PRAGMA foreign_keys = OFF"); err != nil {
return fmt.Errorf("failed to disable foreign key constraints: %w", err)
}
defer func() {
// re-enable foreign key constraints
if _, err := s.db.Exec("PRAGMA foreign_keys = ON"); err != nil {
log.Panic("failed to enable foreign key constraints", zap.Error(err))
}
}()

return s.transaction(func(tx *txn) error {
// defer foreign key checks
if _, err := tx.Exec("PRAGMA defer_foreign_keys=ON"); err != nil {
return fmt.Errorf("failed to defer foreign key checks: %w", err)
}
for _, fn := range migrations[current-1:] {
current++
start := time.Now()
Expand Down
1 change: 1 addition & 0 deletions persist/sqlite/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func sqliteFilepath(fp string) string {
"_foreign_keys=true",
"_journal_mode=WAL",
"_secure_delete=false",
"_synchronous=1",
"_cache_size=-65536", // 64MiB
}
return "file:" + fp + "?" + strings.Join(params, "&")
Expand Down

0 comments on commit 8795e00

Please sign in to comment.