【问题标题】:How can I update my DB with a new version without interference with clients (golang / sqlite3)?如何在不干扰客户端(golang / sqlite3)的情况下使用新版本更新我的数据库?
【发布时间】:2022-12-11 06:53:48
【问题描述】:

我使用的数据库是一个全局变量,初始化读取文件sql-repo.db

const dbFile = "sql-repo.db"

var globalDB *LocalDB

type LocalDB struct {
    Path   string
    handle *sql.DB
}

func InitSqlDB(dbDir string) error {
    if globalDB != nil {
        return nil
    }
    db := LocalDB{Path: filepath.Join(dbDir, dbFile)}
    var err error
    db.handle, err = sql.Open("sqlite3", db.Path)
    if err != nil {
        return err
    }
    globalDB = &db
    return nil
}

有时,我会有这个数据库的更新版本,我可以下载并存储在dbDir

我的想法:

  • 使用ATTACH DATABASE sql-repo.db AS dbMain附加第一个数据库的副本,默认使用。
    当我有新的 .db 文件时,我也附上它 ATTACH DATABASE sql-repo-new.db AS dbNew
    然后我分离dbMain并将dbNew重命名为dbMain
  • 只需更改我的globalDB 指向的地址:
const newDBFile = "sql-repo-new.db"

func PullNewDB(dbDir string) error {
    db := LocalDB{Path: filepath.Join(dbDir, newDBFile)}
    var err error
    db.handle, err = sql.Open("sqlite3", db.Path)
    if err != nil {
        return err
    }
    globalDB = &db
    return nil
}

我怎样才能或应该如何使用新版本/文件更新我的globalDB因为如果我的代码中的客户端连接到数据库并正在查询它,我想避免任何干扰?

我是否应该将 sync.RWMutex 附加到我的 LocalDB 结构,然后在进行更新时锁定/解锁它?
或者我应该使用一个渠道来要求每个客户停止查询数据库?

感谢您的任何帮助/意见/建议!

【问题讨论】:

    标签: database sqlite go mutex go-sqlite3


    【解决方案1】:

    或者您可以启动一个单独的 go 例程或进程,将旧数据库与新文件同步。对从新到旧的所有行进行插入或更新,然后删除缺失的行。如果全部在单个事务中完成,所有查询将读取所有旧数据或新数据而不会阻塞。

    另一个好处是关注点分离,您的应用程序代码不会与更新逻辑聚集在一起,在这种情况下,新文件已损坏,更新事务出错并且不会造成任何损害。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多