пул соединений с базой данных golang sqlite

у меня возникли проблемы с SQLite, бросающим гаечный ключ в моем оборудовании, когда я вызываю запись базы данных в то же самое время, что и чтение. Это происходит, когда разные методы пытаются получить доступ к базе данных в одно и то же время.

то, что я делаю, похоже на то, что делается в этой теме, принято отвечать объясняет, как использовать транзакции базы данных, чтобы избежать блокировок базы данных.

вот некоторые из моих код:

stmt, err := dbtx.Prepare(`statement`)
if err != nil {
    log.Fatal(err)
}

_, err = stmt.Exec(values, values, values)
if err != nil {        
    log.Fatal(err)
}

err = dbtx.Commit()
if err != nil {
    fmt.Println("database lock?")
    fmt.Println(err)
    dbtx.Rollback()
}

fmt.Println("Database storage complete!")

запутанная вещь-программа существует после вывода этого:

database lock?
database is locked
Database storage complete!
2014/09/09 18:33:11 database is locked
exit status 1

Я не хочу, чтобы моя программа останавливалась на блокировке базы данных, я хочу, чтобы она хранила данные в памяти и продолжала заниматься своим делом, пока база данных не будет разблокирована, и я могу попробовать еще раз.

есть ли какой-то стандартный способ достичь этого, может быть, очередь или структура данных какого-то рода, или есть конкретный для базы данных способ решить эту проблему проблема?

почему программа выходит после вывода Database storage complete!?

Edit:

Я считаю, что я исправил проблему, но я не могу быть уверен. Я использую goroutines и соединение с БД по всему пакету. Ранее каждый func в моем коде инициализировал соединение с базой данных при его вызове. Теперь у меня есть" глобальная " переменная для подключения к БД, определенная в верхней части пакета и инициализированная до начала каких-либо процедур. Вот код в в двух словах:

var nDB *sql.DB

позже в главном func...

mypkg.InitDB()
go mypkg.RunDatabaseOperations()
mypkg.BeginHTTPWatcher(rtr)

InitDB() определяется следующим образом:

func InitDB() {
    fmt.Println("Init DB ...")
    var err error
    nDB, err = sql.Open("sqlite3", "./first.db")
    if err != nil {
        log.Fatal(err)
    }
    if nDB == nil {
        log.Fatal(err)
    }
    fmt.Printf("nDB: %vn", ODB)
    fmt.Println("testing db connection...")
    err2 := nDB.Ping()
    if err2 != nil {
        log.Fatalf("Error on opening database connection: %s", err2.Error())
    }
}

и RunDatabaseOperations периодически сканирует интернет-ресурс на наличие данных и сохраняет их в базе данных при изменении (раз в несколько секунд). BeginHTTPWatcher прослушивает HTTP-запросы, так что данные могут быть считаны из запущенной программы и передается по сети, запрос данных, будь то локальный или внешний запрос. У меня не было пока проблема.

2 ответов


на документация говорит:

один экземпляр соединения и все его производные объекты(подготовленные операторы, операции резервного копирования и т. д.) не может использоваться одновременно из нескольких goroutines без внешней синхронизации.

(Это другой драйвер SQLite, но это ограничение также относится к вашему.)

когда вы используете goroutines, вы должны использовать отдельную базу данных подключение.

по умолчанию SQLite немедленно прерывается при обнаружении базы данных, заблокированной другой транзакцией. Чтобы разрешить больше параллелизма, вы можете сказать ему подождать завершения другой транзакции, установив тайм-аут занятости.

использовать BusyTimeout функция, если ваш драйвер SQLite имеет его, или выполните PRAGMA busy_timeout команда SQL напрямую.


пожалуйста, опубликуйте больше своего кода, чтобы мы могли получить более полное представление о том, что происходит.

однако, вот пара мыслей. Golang пулы db соединения по умолчанию (хотя, CENTOS, кажется, возможно, нет..). Кроме того, ваша программа "останавливается", потому что она ждет открытого соединения из пула соединений db. Если вы хотите, чтобы остальная часть вашей программы продолжалась в течение этого времени, вы должны запустить ее как асинхронную функцию-check out горутин вот!--4-->. Это фактически приведет к тому, что ваша программа будет стоять в очереди, как вы хотите, так как соединения будут назначены в том порядке, в котором они были запрошены, когда они станут доступными. подробнее здесь если вас интересуют внутренние органы.

Если вам нужны фрагменты кода для того, как может выглядеть ваш goroutine, сообщите нам об этом.