Golang中如何存储多个数据库连接

Golang中如何存储多个数据库连接 大家好,

我在一台服务器上有10个Oracle数据库,我尝试存储所有这些数据库的连接,但当我尝试执行查询时,我得到的结果是来自同一个数据库的10次重复。请帮忙。

type dbConn struct {
db *sql.DB
}
func oracledb_sql_connection(orcldb_repo_data []string, db_home_bin string, logfile string, debug bool) []dbConn {
	var inst_temp, oracle_home, ld_library_path, path string
	var db_connection_arr []dbConn
	for _, j := range orcldb_repo_data {
		for i := 0; i <= 2; i++ {
			inst_temp = j[:len(j)-i]
			ora_result, _ := exec.Command("grep", inst_temp, "/etc/oratab").Output()
			if len(ora_result) > 0 {
				inst_temp = fmt.Sprint(strings.TrimSpace(strings.Split(string(ora_result), ":")[0]))
				break
			}
		}

		//Setting DB Enviornment
		os.Setenv("ORACLE_SID", inst_temp)
		orcldb_home, err := exec.Command("sh", db_home_bin, inst_temp).Output()
		if err != nil {
			break
		}
		oracle_home = fmt.Sprint(strings.TrimSpace(string(orcldb_home)))
		os.Setenv("ORACLE_HOME", oracle_home)
		ld_library_path = os.Getenv("ORACLE_HOME") + "/lib"
		os.Setenv("LD_LIBRARY_PATH", ld_library_path)
		if !strings.Contains(os.Getenv("PATH"), os.Getenv("ORACLE_HOME")) {
			path = os.Getenv("PATH") + ":" + os.Getenv("ORACLE_HOME") + "/bin"
			os.Setenv("PATH", path)
		}
		os.Setenv("ORACLE_SID", j)

		////////////////////////////////////

		//Connection to database
		connect_string := "/ as sysdba"
		db, err := sql.Open("godror", connect_string)
		if err != nil {
			break
		}
		//defer db.Close()
		fmt.Println(db)
		fmt.Println("DB Connection Open")
		db.Conn()
		db_connection_arr = append(db_connection_arr, dbConn{db})
	}

	return db_connection_arr
}

更多关于Golang中如何存储多个数据库连接的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

我在顺序使用它时没有存储数据库连接,并且它是正常工作的。但是当我尝试存储数据库连接时,它就不行了。

在存储数据库连接的过程中存在一些问题,我们需要弄清楚。

更多关于Golang中如何存储多个数据库连接的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


ankurnigam:

		connect_string := "/ as sysdba"
		db, err := sql.Open("godror", connect_string)

你在每次循环迭代中都使用相同的连接字符串调用 sql.Open。也许你认为设置环境变量 ORACLE_SID 会影响结果,可能是我遗漏了什么,但我没有在驱动程序的文档中看到任何关于它使用环境变量来建立连接的信息。

pkg.go.dev

godror package - github.com/godror/godror - Go Packages

Package godror is a database/sql/driver for Oracle DB.

godror

godror

GO DRiver for ORacle DB

问题在于你使用了环境变量来配置连接,而环境变量是全局的。每次循环迭代时,你都在修改相同的环境变量(ORACLE_SID等),导致所有连接都指向最后一个设置的数据库。你需要为每个连接使用独立的配置。

以下是修改后的代码,使用连接字符串而不是环境变量来区分不同的数据库:

type dbConn struct {
    db *sql.DB
    sid string
}

func oracledb_sql_connection(orcldb_repo_data []string, db_home_bin string, logfile string, debug bool) []dbConn {
    var db_connection_arr []dbConn
    
    for _, j := range orcldb_repo_data {
        // 获取ORACLE_HOME(这部分可以保留,因为不直接影响连接)
        var inst_temp string
        for i := 0; i <= 2; i++ {
            inst_temp = j[:len(j)-i]
            ora_result, _ := exec.Command("grep", inst_temp, "/etc/oratab").Output()
            if len(ora_result) > 0 {
                inst_temp = fmt.Sprint(strings.TrimSpace(strings.Split(string(ora_result), ":")[0]))
                break
            }
        }
        
        // 使用完整的连接字符串,包含SID
        connect_string := fmt.Sprintf("user=sys password=your_password sid=%s sysdba=true", j)
        db, err := sql.Open("godror", connect_string)
        if err != nil {
            fmt.Printf("连接数据库 %s 失败: %v\n", j, err)
            continue
        }
        
        // 测试连接
        err = db.Ping()
        if err != nil {
            fmt.Printf("Ping数据库 %s 失败: %v\n", j, err)
            db.Close()
            continue
        }
        
        fmt.Printf("成功连接到数据库: %s\n", j)
        db_connection_arr = append(db_connection_arr, dbConn{db: db, sid: j})
    }
    
    return db_connection_arr
}

// 使用示例
func main() {
    databases := []string{"DB1", "DB2", "DB3", "DB4", "DB5", "DB6", "DB7", "DB8", "DB9", "DB10"}
    connections := oracledb_sql_connection(databases, "/path/to/db_home_bin", "log.txt", false)
    
    // 执行查询
    for _, conn := range connections {
        rows, err := conn.db.Query("SELECT * FROM your_table")
        if err != nil {
            fmt.Printf("查询数据库 %s 失败: %v\n", conn.sid, err)
            continue
        }
        defer rows.Close()
        
        // 处理结果
        fmt.Printf("从数据库 %s 获取数据\n", conn.sid)
    }
    
    // 记得关闭所有连接
    defer func() {
        for _, conn := range connections {
            conn.db.Close()
        }
    }()
}

如果你需要使用操作系统认证(/ as sysdba),可以这样修改连接字符串:

// 使用操作系统认证
connect_string := fmt.Sprintf("oracle://?sysdba=1&sid=%s", j)
db, err := sql.Open("godror", connect_string)

关键点是:

  1. 不要在循环中修改全局环境变量
  2. 为每个连接使用独立的连接字符串
  3. 在结构体中存储SID以便识别
  4. 添加连接测试(Ping)
  5. 正确处理连接关闭

这样每个连接都会指向正确的数据库,不会出现重复数据的问题。

回到顶部