Skip to content

Reading via a large number of goroutines breaks #289

Closed
@anantn

Description

Reading from more than ~1000 goroutines simultaneously fails with an error "unable to open database file". Test program is attached. You can tweak maxRoutines to see the normal/broken behavior, on my local tests everything works fine until about 1000 goroutines.

package main

import (
    "database/sql"
    "fmt"
    "log"
    "math/rand"
    "os"
    "sync"

    _ "github.com/mattn/go-sqlite3"
)

const (
    maxKeys     = 20
    maxRoutines = 5000
)

func main() {
    // Create DB.
    os.Remove("./test.db")
    destDb, err := sql.Open("sqlite3", "./test.db")
    if err != nil {
        log.Fatal(err)
    }
    defer destDb.Close()
    destDb.Ping()

    // Create table.
    _, err = destDb.Exec("create table test(id int, value text)")
    if err != nil {
        log.Fatal(err)
    }

    // Write 20 values.
    for i := 0; i < maxKeys; i++ {
        _, err = destDb.Exec(fmt.Sprintf("insert into test values(%d, 'random_value')", i))
        if err != nil {
            log.Fatal(err)
        }
    }

    // Now test.
    stressTest(destDb)
    fmt.Printf("Success!\n")
}

func stressTest(db *sql.DB) {
    // Read values from all of these simultaneously.
    var wg sync.WaitGroup
    for i := 0; i < maxRoutines; i++ {
        wg.Add(1)
        go read(i, db, &wg)
    }
    wg.Wait()
}

func read(num int, db *sql.DB, wg *sync.WaitGroup) {
    defer wg.Done()
    _, err := db.Query(fmt.Sprintf("select value from test where id=%d", rand.Intn(maxKeys)))
    if err != nil {
        fmt.Printf("Goroutine %d failed read : %v\n", num, err)
    }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions