4

I'm writing a golang web application. The web application accesses the file system (reading and writing) and an sqlite3 database file.

Question 1: How can I synchronize file system access in Go?

type DataObject struct {
  data []byte
}

func (*d DataObject) Write() {
   //
   // Synchronization ?
   //
   ioutil.WriteFile("file.name", d.data, 0644)
   //
   // Stop synchronization ?
   //
}

Question 2: Do I need to synchronize sqlite3 database file access?

type SqlObject struct {
  sqldata string
}

func (*s SqlObject) Store() error {
  //
  // Open the file, do I need some sort of synchronization?
  //
  con, err := sqlite.Open("database/datafile.db")
  if err != nil {
    return err
  }
  defer con.Close()

  err = con.Exec("INSERT INTO data(sqldata) values(?)", s.sqldata)
  if err != nil {
    return err
  }
  return nil
}

I'm using the gosqlite3 driver (http://code.google.com/p/gosqlite/).

4

4 回答 4

7

对于文件,这取决于您的应用程序。如果您只有一个 goroutine 写入文件,则不需要。如果不止一个,则取决于:

如果你在不同的进程(程序)之间进行协调,你可以使用flock(它可能不会很有趣)。

如果您在程序中协调多个 goroutine,您可以使用互斥锁,或者您可以查看是否可以重新组织程序,以便只有一个例程写入文件,其他例程通过通道发送更新。

对于 SQLite,我相信最简单的方法是保持一个 sqlite 连接打开并从各种 goroutine 中使用它;尽管它确实支持同时打开多个进程,并且如果您的系统执行许多并发读取可能会更快(它使用全局锁进行写入)。

于 2013-02-08T20:12:17.560 回答
4

问题 1

" sync"包提供 Lock 和 RWLock 用于以常规方式同步对资源的访问。虽然这没有什么问题,但我喜欢玩成语,所以我可能会做这样的事情

package main

import "fmt"

func SyncFile(path string) chan<- func(string) {
    ch := make(chan func(string))
    go func() {
        for process := range ch {
            process(path)
        }
    }()
    return ch
}

func main() {
    data := SyncFile("data.name")
    data <- func(path string) {
        fmt.Println(path)
    }
}

那么如果你只通过这个funcs通道访问文件,访问将是同步的。这是可靠的,但是您也许可以找到更有效的方法。

问题2

gosqlite3 驱动程序只是与 libsqlite3 的 Go 绑定,因此适用SQLite 常见问题解答(看起来您对此很清楚)。如果您希望这两者相互同步,那么只需将 SQLite 用法包装在文件访问同步代码中即可。

于 2013-02-08T20:08:07.903 回答
3

1)您应该使用读/写互斥锁(在 go std 库中)。代码看起来像:

import "sync" // http://golang.org/pkg/sync/
const (
    filename = "file.name"
)
var globalFileLock sync.RWMutex

type DataObject struct {
  data []byte
}

func (*d DataObject) Write() {
   globalFileLock.Lock()
   defer globalFileLock.Unlock()
   ioutil.WriteFile(filename, d.data, 0644)
}

func (*d DataObject) Read() {
   globalFileLock.RLock()
   defer globalFileLock.RUnlock()
   d.data = ioutil.ReadFile(filename)
}

2)由于您尚未从程序中发布“导入”部分,因此我不知道您使用的是哪个 sqlite 驱动程序。

如果您使用 database/sql 打开数据库连接,驱动程序提供 goroutine 之间的并发控制。

于 2013-02-09T07:05:25.910 回答
-1

我知道这是一个老问题,但由于我有同样的“数据库锁定”问题,并且一个事务为我解决了它,我想我会在这里提到它:

db, err := sql.Open("sqlite3", db_path)
if err != nil {
    log.Printf("Cannot connect to database: %s\n", err ) 
}
defer db.Close()
tx, _ := db.Begin() 
var value string
err = tx.QueryRow("SELECT X FROM Y").Scan(&value)
tx.Rollback() // or: tx.Commit()
于 2014-05-26T19:26:47.390 回答