dstm2014
2013-02-08 19:16
浏览 67

Golang Web应用程序中的同步

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/).

图片转代码服务由CSDN问答提供 功能建议

我正在编写golang Web应用程序。 Web应用程序访问文件系统(读写)和sqlite3数据库文件。

问题1:如何在Go中同步文件系统访问? / p>

  type DataObject struct {
 data [] byte 
} 
 
func(* d DataObject)Write(){
 // 
 //同步?\  n // 
 ioutil.WriteFile(“ file.name”,d.data,0644)
 // 
 //停止同步?
 // 
} 
   \  n 
 

问题2:是否需要同步sqlite3数据库文件访问?

 类型SqlObject结构 {
 sqldata string 
} 
 
func(* s SqlObject)Store()错误{
 // 
 //打开文件,我需要某种同步吗?
 // 
 con,  err:= sqlite.Open(“ database / datafile.db”)
如果err!= nil {
返回err 
} 
推迟con.Close()
 
 err = con.Exec(“ INSERT  INTO data(sqldata)values(?)“,s.sqldata)
如果err!= nil {
 return err 
} 
 return nil 
} 
   
 \  n 

我正在使用gosqlite3驱动程序( http://code.google.com/p/gosqlite/ )。

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • dongzhu6900 2013-02-08 20:12
    已采纳

    For files it depends on your application. If you only have one goroutine writing to the file, you shouldn't need to. If more than one then it depends:

    If you are coordinating between different processes (programs) you can use flock (and it probably won't be fun).

    If you are coordinating multiple goroutines in your program you can use mutexes or you can see if you can re-organize the program so just one routine writes to the file and the others send updates via channels.

    For SQLite I believe the easiest way would be to just keep one sqlite connection open and use that from the various goroutines; though it does support multiple processes having it open at once and if your system does many concurrent reads that might be faster (it uses a global lock for writing).

    已采纳该答案
    打赏 评论
  • douyanning3724 2013-02-08 20:08

    Question 1

    The "sync" package provides Lock and RWLock for synchronizing access to resources in the conventional way. While there's nothing wrong with that, I like playing around with idioms so I might do something like this:

    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)
        }
    }
    

    Then if you only access the file through this channel of funcs, access will be synchronized. This is reliable, but you may be able to find something more efficient.

    Question 2

    The gosqlite3 driver is just a Go binding to libsqlite3, so the SQLite FAQ applies (and it looks like you're in the clear on this). If you want both of these to be synchronized with each other, then just wrap the SQLite usage inside the file access synchronization code.

    打赏 评论
  • duandazhen7306 2013-02-09 07:05

    1) You should use a read/write mutex (in the go std library). Code would look something like:

    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) As you haven't posted the 'import' section from your program, I don't know which sqlite driver you're using.

    If you are using database/sql to open the database connection, the driver provides concurrency control between goroutines.

    打赏 评论
  • douhui1333 2014-05-26 19:26

    I know its an old question but since I had the same "db lock" problem, and a transaction resolved it for me, I thought I'd mention it here:

    db, err := sql.Open("sqlite3", db_path)
    if err != nil {
        log.Printf("Cannot connect to database: %s
    ", err ) 
    }
    defer db.Close()
    tx, _ := db.Begin() 
    var value string
    err = tx.QueryRow("SELECT X FROM Y").Scan(&value)
    tx.Rollback() // or: tx.Commit()
    
    打赏 评论

相关推荐 更多相似问题