“纵有疾风来,人生不言弃”,这句话送给正在学习Golang的朋友们,也希望在阅读本文《使用 Go 从一个 postgres 数据库复制到另一个》后,能够真的帮助到大家。我也会在后续的文章中,陆续更新Golang相关的技术文章,有好的建议欢迎大家在评论留言,非常感谢!
问题内容我想使用 go 将 postgres 数据从数据库 a、视图 a 复制到数据库 b、表 b。这将针对几十个表完成,我想利用 go 提供的并发性。
我可以使用 psql 命令行来完成此操作,如下所示:
psql -h hostserver -p 5432 -u dbuser -d dbname \
-c "\copy (select * from myview) to stdout" \
| psql -h destinationhost -p 5432 -u dbuser -d destinationdb \
-c "\copy destinationtable from stdin"
或者在 python 中运行上述命令或使用 os.pipe 和 psycpog2 的 copy_from/to 命令。不幸的是,这些选项似乎都不太适合并发性。这就是为什么我希望在 go 中做同样的事情。
所以我的问题 - 如何在 go 中运行上述命令行命令?或者通过管道将数据传入/传出不同的 postgres 数据库?我一直在尝试以下代码,但没有成功。任何提示将不胜感激。
import "github.com/go-pg/pg"
//connect to source and destination db's (successful connection confirmed)
r, w := io.Pipe()
println("start")
_, err := destDB.CopyFrom(r, "COPY destinationTable FROM STDIN")
if err != nil {
println(err)
}
_, err = srcDB.CopyTo(w, "COPY (SELECT * FROM sourceView) TO STDOUT")
if err != nil {
println(err)
}
srcDB.Close()
destDB.Close()
解决方案
读取器和写入器应该位于不同的 goroutine 中,并且完成后应该关闭管道的写入侧,以防止读取侧挂起。请参阅以下内容作为起点:
r, w := io.Pipe()
writer := make(chan error)
go func() {
defer w.Close()
_, err := src.CopyTo(w, `COPY (SELECT * FROM sourceView) TO STDOUT`)
writer <- err
}()
reader := make(chan error)
go func() {
_, err := dest.CopyFrom(r, "COPY destinationTable FROM STDIN")
reader <- err
}()
errWriter := <-writer
if errWriter != nil {
fmt.Printf("Writer (CopyTo) error: %v", errWriter)
}
errReader := <-reader
if errReader != nil {
fmt.Printf("Reader (CopyFrom) error: %v", errReader)
}
if errWriter == nil && errReader == nil {
fmt.Println("All done - no errors")
}
今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注编程网公众号,一起学习编程~