4

私はgolangWebアプリケーションを書いています。Webアプリケーションは、ファイルシステム(読み取りと書き込み)とsqlite3データベースファイルにアクセスします。

質問1: Goでファイルシステムアクセスを同期するにはどうすればよいですか?

type DataObject struct {
  data []byte
}

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

質問2: sqlite3データベースファイルアクセスを同期する必要がありますか?

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
}

gosqlite3ドライバー(http://code.google.com/p/gosqlite/)を使用しています。

4

4 に答える 4

7

ファイルの場合は、アプリケーションによって異なります。ファイルへの書き込みが1つしかない場合は、その必要はありません。複数ある場合は、以下によって異なります。

異なるプロセス(プログラム)間で調整している場合は、flockを使用できます(おそらく面白くないでしょう)。

プログラムで複数のゴルーチンを調整している場合は、ミューテックスを使用するか、プログラムを再編成して、1つのルーチンだけがファイルに書き込み、他のルーチンがチャネルを介して更新を送信できるかどうかを確認できます。

SQLiteの場合、最も簡単な方法は、1つのsqlite接続を開いたままにして、さまざまなゴルーチンからそれを使用することだと思います。ただし、一度に開いている複数のプロセスをサポートし、システムが多数の同時読み取りを実行する場合は、より高速になる可能性があります(書き込みにグローバルロックを使用します)。

于 2013-02-08T20:12:17.560 に答える
4

質問1

同期」パッケージは、従来の方法でリソースへのアクセスを同期するためのロックと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)
    }
}

次に、この機能チャネルを介してのみファイルにアクセスすると、アクセスが同期されます。これは信頼できますが、もっと効率的なものを見つけることができるかもしれません。

質問2

gosqlite3ドライバーはlibsqlite3へのGoバインディングであるため、SQLite FAQが適用されます(これについては明確になっているようです)。これらの両方を相互に同期させたい場合は、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を使用してデータベース接続を開く場合、ドライバーはゴルーチン間の同時実行制御を提供します。

于 2013-02-09T07:05:25.910 に答える
-1

私はそれが古い質問であることを知っていますが、同じ「dbロック」の問題があり、トランザクションによって解決されたので、ここで言及したいと思いました。

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 に答える