Estou vendo a mensagem de erro "Too man connections" ao chamar db.sqlDB.Query (). Antes de me aprofundar neste problema, gostaria de saber se hĂĄ um problema conhecido.
Pensamentos?
013/07/23 03:05:35 yy.UpdateThingy () db.go: 264 [Falha ao inserir registro em XXXX: Erro 1040: muitas conexÔes]
Estou usando go versĂŁo 1.1.1:
go versĂŁo go1.1.1 linux / 386
Estou usando a versĂŁo do driver mysql:
v1.0.1
VersĂŁo MySql:
VersĂŁo do servidor: 5.5.22-0ubuntu1 (Ubuntu)
Aqui estĂĄ um exemplo de uma das minhas consultas:
linhas, errar =
db.sqlDB.Query ("inserir em XXXX (aaaa) valor (?)",
connect.ZZZZ)
se errar! = nulo {
_ = linhas.Fechar ();
resultado de retorno, err
}
_ = linhas.Fechar ();
Eu adicionei "rows.Close ()" esperando que corrigisse o problema, mas sem dados.
Para sua informação, algumas das minhas consultas usam "rows.Scan" e outras não.
DĂȘ uma olhada aqui: https://github.com/VividCortex/go-database-sql-tutorial
NĂŁo use .Query, use .Exec.
VocĂȘ tem muitos acessos simultĂąneos ao banco de dados. Nesse caso, vocĂȘ deve limitar manualmente o nĂșmero de conexĂ”es simultĂąneas atĂ© que o pacote de banco de dados / sql forneça um mecanismo de bloqueio em uma versĂŁo futura para isso. Mas, em muitos casos, o armazenamento em cache / atualizaçÔes assĂncronas seria a melhor alternativa.
Muito provavelmente, seu programa estĂĄ apenas vazando conexĂ”es de banco de dados. Isso acontece se vocĂȘ nĂŁo fechar o rows
retornado por db.Query
ou se esquecer de encerrar as transaçÔes (no banco de dados / API tx do sql ).
Meu conselho geral Ă© usar
db.Exec
se vocĂȘ nĂŁo espera uma linha retornada (em outras palavras, vocĂȘ nĂŁo Scan
nada). A conexão é imediatamente liberada após a execução.db.QueryRow
se vocĂȘ espera uma linha. Se vocĂȘ usar a sintaxe encadeada , vocĂȘ nĂŁo pode vazar conexĂ”esdb.Query
se vocĂȘ espera vĂĄrias linhas. Ă muito importante que vocĂȘ "libere" a conexĂŁo lendo todas as linhas retornadas (fazendo um loop de rows.Next
) ou chamando rows.Close
. Para ter certeza, adiar uma chamada de rows.Close
é uma boa ideia. Não se esqueça dos casos de erro, etc.Mudei "db.Query ()" para "db.Prepare () e db.Exec ()" e isso corrigiu meu problema. Obrigado pelas respostas råpidas e excelentes.
Eu também tenho isso.
e, eu uso "db.Prepare () e db.Exec ()",
var db * sql.DB
função getdb () * sql.DB {
db, err = sql.Open ("mysql", connArgs)
db.SetMaxIdleConns (100)
return db
}
função foo (db * sql.DB) {
faça alguma coisa .....
smint, err: = db.Prepare (....)
adiar smint.Close ()
smint.Exec (....)
}
func main () {
go func () {
db = get_db ()
adiar db.Close ()
foo (db)
} ()
}
tente ir 1.3
----- A mensagem original -----
De: liutaihua [email protected]
DestinatĂĄrio: go-sql-driver / mysql [email protected]
Assunto: Re: [mysql] Muitas conexÔes (# 111)
Data: 15:43, 16 de julho de 2014
e ... por que vocĂȘ inicia uma goroutine no principal?
Se seu cĂłdigo realmente se parece com isso, main pode (e provavelmente sairĂĄ) antes que o goroutine seja executado e seu programa nĂŁo farĂĄ nada.
Basta remover go func(){
e }()
. VocĂȘ ficarĂĄ melhor.
desculpe pela minha descrição, na verdade, código:
função socke_server () {
para {
// aceitar_algumacoisa_from_socket como receber
go func (some_receive) {
db = get_db ()
adiar db.Close ()
foo (db)
}
}
}
func main () {
socke_server ()
}
Mas, agora, eu uso o protocolo de domĂnio Unix (' user: pwd @ unix (/tmp/mysql.sock)/'), foi corrigido.
obrigado resposta
VocĂȘ tambĂ©m nĂŁo deve fazer isso - pode funcionar, mas Ă© lento.
Coloque o loop de aceitação em principal.
Converta a goroutine em uma função de nĂvel superior.
Coloque seu código get_db no topo de seu db.Closer principal e adie lå também (e somente lå).
NĂŁo abra e feche o banco de dados assim.
Experimente o seguinte cĂłdigo:
func handleConnection(db *sql.DB, args...interface{}) {
// do someting.....
// db.Exec("STATEMENT", args...)
}
func main() {
db, err := sql.Open("mysql", connArgs)
if err != nil {
panic(err)
}
db.SetMaxIdleConns(100)
defer db.Close()
for {
// accept connections and pass relevant stuff to handleConnection
go handleConnection(db, nil)
}
}
Obrigado, entendi.
ComentĂĄrios muito Ășteis
Opção 1: concorrĂȘncia muito alta
VocĂȘ tem muitos acessos simultĂąneos ao banco de dados. Nesse caso, vocĂȘ deve limitar manualmente o nĂșmero de conexĂ”es simultĂąneas atĂ© que o pacote de banco de dados / sql forneça um mecanismo de bloqueio em uma versĂŁo futura para isso. Mas, em muitos casos, o armazenamento em cache / atualizaçÔes assĂncronas seria a melhor alternativa.
Opção 2: Vazamento de conexÔes
Muito provavelmente, seu programa estĂĄ apenas vazando conexĂ”es de banco de dados. Isso acontece se vocĂȘ nĂŁo fechar o
rows
retornado pordb.Query
ou se esquecer de encerrar as transaçÔes (no banco de dados / API tx do sql ).Meu conselho geral é usar
db.Exec
se vocĂȘ nĂŁo espera uma linha retornada (em outras palavras, vocĂȘ nĂŁoScan
nada). A conexão é imediatamente liberada após a execução.db.QueryRow
se vocĂȘ espera uma linha. Se vocĂȘ usar a sintaxe encadeada , vocĂȘ nĂŁo pode vazar conexĂ”esdb.Query
se vocĂȘ espera vĂĄrias linhas. Ă muito importante que vocĂȘ "libere" a conexĂŁo lendo todas as linhas retornadas (fazendo um loop derows.Next
) ou chamandorows.Close
. Para ter certeza, adiar uma chamada derows.Close
é uma boa ideia. Não se esqueça dos casos de erro, etc.