Mysql: Muitas conexÔes

Criado em 23 jul. 2013  Â·  9ComentĂĄrios  Â·  Fonte: go-sql-driver/mysql

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.

question working as intended

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 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Ă”es
  • db.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.

Todos 9 comentĂĄrios

DĂȘ uma olhada aqui: https://github.com/VividCortex/go-database-sql-tutorial

NĂŁo use .Query, use .Exec.

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 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Ă”es
  • db.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.

Esta pĂĄgina foi Ăștil?
0 / 5 - 0 avaliaçÔes