Mysql: Странная ошибка при разорванном соединении

Созданный на 5 дек. 2013  ·  25Комментарии  ·  Источник: go-sql-driver/mysql

Когда я убиваю соединения, у которых есть длительные запросы, я получаю что-то вроде этого:

[MySQL] 2013/12/05 22:17:19 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:19 statement.go:24: Invalid Connection
[MySQL] 2013/12/05 22:17:27 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:27 statement.go:24: Invalid Connection
[MySQL] 2013/12/05 22:17:39 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:39 statement.go:24: Invalid Connection

Я привык видеть эту ошибку:

2013 (HY000) at line 1: Lost connection to MySQL server during query

Насколько мне известно, эта ошибка фактически отправляется через сетевое соединение обратно клиенту, которого убили. Это замаскировано в драйвере или базе данных / sql, или это не ошибка, передаваемая по протоколу, как я думаю? Можем ли мы как-нибудь прояснить, что происходит?

bug thinking

Самый полезный комментарий

Думаю, проблема в этом:

package main

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, _ := sql.Open("mysql", "/")
    defer db.Close()
    tx, err := db.Begin()
    if err != nil {
        panic(err)
    }
    defer tx.Commit()
    stmt1, err := tx.Prepare("SELECT 1")
    if err != nil {
        panic(err)
    }
    rows1, err := stmt1.Query()
    if err != nil {
        panic(err)
    }
    stmt2, err := tx.Prepare("SELECT 2")
    if err != nil {
        // rows1 is not closed -> triggers busy buffer because transaction is on one connection
        // and stmt1, stmt2 use the same one.
        // Move rows1.Close() in front of tx.Prepare and it disappears
        panic(err)
    }
    rows2, err := stmt2.Query()
    if err != nil {
        panic(err)
    }
    rows1.Close()
    rows2.Close()
    stmt1.Close()
    stmt2.Close()
}

Все 25 Комментарий

Нет, ошибка не передается. Ошибка на самом деле в том, что ничего нельзя получить: wink:
Но было бы неплохо напечатать более информативное сообщение об ошибке, чем EOF

Я предполагаю, что ошибки statement.go:24: Invalid Connection являются результатом http://golang.org/issue/5718
Эти ошибки должны исчезнуть, когда логика автоматического переподключения будет исправлена ​​в пакете database / sql.

EOF - это просто io.EOF , я не уверен, следует ли нам фильтровать и заменять это. Это своего рода идиома Go для использования ее в подобных случаях (например, в сетевом пакете, откуда возникла эта ошибка). Но хотя бы смысл должен быть где-то задокументирован.

Каково твое мнение?

Я тоже хотел бы услышать, что об этом думает

Я следил за кодом в базе данных / sql. Ошибки statement.go:24: Invalid Connection не являются результатом http://golang.org/issue/5718 , хотя я согласен с @julienschmidt в том, что пакет должен попытаться повторить попытку. Существует до десяти попыток для вызовов Query() и Exec() при запуске на уровне БД, но ни одной попытки при использовании приемника Stmt.

«Недействительное соединение» @xaprb увидело из-за того, что соединение MySQL больше не доступно, когда Close() вызывается для подготовленного оператора, то есть stmt.mc.netConn здесь равно нулю. Это безобидное сообщение, потому что соединение с базой данных / sql будет закрыто, как только будет возвращено ErrBadConn .

Но это не единственная возможность, которую я видел; database / sql (Go 1.2) могут иметь некоторые проблемы с параллелизмом, которые также могут закончиться этим сообщением. Если оператор (database / sql) закрывается, когда его использует подключение драйвера, оператор драйвера планируется закрыть в следующий putConn() по noteUnusedDriverStatement() . Но putConn() может выполняться до removeOpenStmt() (см. (*Stmt) finalClose() ). Если после вызова ожидающих функций onPut само соединение закрывается из-за лимита неактивного соединения, то пакет снова попытается закрыть оператор, в результате чего появится сообщение. Это опять же безвредно, но, тем не менее, раздражает.

IMHO База данных Go / sql требует тщательного пересмотра ...

@gkristic вы предлагаете какие-либо изменения в драйвере?

В пакете database / sql есть несколько недостатков, я надеюсь внести несколько улучшений в Go 1.3. Пересмотр управления зависимостями - один из пунктов моего списка.

Если вы обнаружите подобные проблемы, сообщите об этом на странице https://code.google.com/p/go/issues/list.

Учитывая, что эти условия (а именно, потеря соединения или двойное закрытие базы данных / sql) безвредны, я бы ожидал, что драйвер пропустит их молча, вместо того, чтобы печатать сообщение «Недопустимое соединение». На мой взгляд, последнее может быть либо: страшным, если вы не знаете, что оно безвредно; раздражает, когда вы это делаете; но, возможно, вводит в заблуждение, если где-то еще напечатано идентичное сообщение (а оно есть, за исключением номера строки), скрывающее настоящее предупреждение, которое вы можете легко пропустить. Если stmt.mc или stmt.mc.netConn равны нулю в инструкции Close() function, я бы предпочел возврат без дальнейшей регистрации. Также обратите внимание, что возврат driver.ErrBadConn туда (как представлено в 4d3764bbcb17c31575642626baeab1bcdc30c301) не имеет абсолютно никакого эффекта, потому что база данных / sql никогда не проверяет код возврата для закрытия оператора.

В качестве примечания, я бы, вероятно, добавил функцию для настройки регистратора. В настоящее время errLog инициализируется внутри пакета и является частным. Он выводит стандартную ошибку, которая может быть, а может и не быть; т.е. процесс может закрыть дескриптор по другим причинам. Но даже если это не так, у пользователя может быть другое представление о ведении журнала (подумайте о файлах, системном журнале и т. Д.). Драйвер может предоставить этот регистратор по умолчанию, но может также позволить пользователю установить другое.

Как только у меня появится свободное время, я подготовлю небольшой пример проблемы, о которой упоминал ранее, и напишу отчет.

Спасибо!

@gkristic по поводу регистратора - вы имеете в виду что-то вроде https://github.com/go-sql-driver/mysql/pull/182 (слился с мастером неделю назад)?

@arnehormann О, чувак ... именно это. Работаю с v1.1. Я проверил и другие вещи у мастера перед публикацией, но забыл проверить логирование. Извините и спасибо!

@gkristic вообще не проблема

Какие изменения следует внести до следующего выпуска? PR приветствуются :)

Привет, ребята, здесь новый пользователь go-sql-driver. Я замечаю похожие проблемы, но мне было интересно, может ли кто-нибудь помочь мне подтвердить, что причина та же? В длительных стажах, использующих горутины, я обычно получаю следующее.

[MySQL] 2014/05/14 20:33:05 packets.go:356: Busy buffer
[MySQL] 2014/05/14 20:33:05 packets.go:73: EOF
[MySQL] 2014/05/14 20:33:05 statement.go:24: Invalid Connection
[MySQL] 2014/05/14 20:33:05 connection.go:206: Invalid Connection

Я более чем готов запачкать руки здесь, просто ищу руководство о том, как подойти к проблеме. Можно ли игнорировать эту ошибку «Недопустимое соединение» при определенных обстоятельствах? Есть ли способ автоматически захватить другое соединение, если это обнаружено?

Ох, ох ... теперь, когда я понял , я пропустил комментарий Прошу прощения, Жюльен.) этот комментарий. «Недействительное соединение» на statement.go: 24 безвредно. Драйвер должен поступить соответствующим образом, выбрав другое соединение. Я не уверен насчет «занятого буфера»; Я не помню, чтобы видел это. Я давно не проверял этот код. Я выделю немного времени, чтобы взглянуть на него еще раз и посмотреть, смогу ли я чем-то помочь. К сожалению, этого не произойдет до конца следующей недели. Но к тому времени я к вам еще вернусь.

@rmulley : Мне кажется, это не связано с этой проблемой.
Пожалуйста, попробуйте воспроизвести эту ошибку с текущей основной версией git, если вы использовали версию, установленную go get (это более старая версия).
Пожалуйста, откройте новый выпуск. Определенно поможет минимальный образец кода, запускающий эту ошибку.

Похоже, что (b *buffer) takeBuffer возвращает nil . Кажется, это происходит только тогда, когда b.length > 0 . Это будет означать, что по какой-то причине в буфере есть непрочитанные данные.
Я никогда раньше не видел этой ошибки и реализовал эти дополнительные проверки только для дополнительной безопасности. Никогда бы не поверил в эту ошибку в дикой природе.

Согласно № 206 эта ошибка фактически исчезает при запуске go с наконечника. Разве это не так?

Во-первых, извините за поздний ответ. Я был в отпуске, а потом забыл следить. Я убедился, что у меня установлена ​​последняя версия драйвера MySQL, и сейчас тестирую Go 1.3. Похоже, теперь я вижу более подробную информацию в сообщении об ошибке.

[MySQL] 2014/06/23 11:46:04 packets.go:356: Busy buffer
[MySQL] 2014/06/23 11:46:04 packets.go:73: read tcp xxx.xxx.xxx.xx:3306: connection reset by peer

Это проблема MySQL на моей стороне? (Я не нашел в Интернете ничего полезного о том, как решить эту проблему)
Или это то, что я могу проверить, а затем как-то переподключить в своем коде?

Я столкнулся с той же проблемой, что описал Рмулли. отличие состоит в том, что «занятый буфер» появляется в очень коротком запросе (всего 1 запрос + 2 Exec).

Я чувствую, что проблема связана с подготовленными заявлениями. я обнаружил, что если я подготовил оператор в транзакции, например

 stmt, err = tx.Prepare("SELECT ...")

я должен закрыть этот stmt, прежде чем я подготовлю другой оператор, иначе я каждый раз буду сталкиваться с «занятым буфером». если я не использую подготовленные операторы, например, выполняю непосредственно tx, например

 tx.Query("...")

или же

tx.Exec("...")

, это было хорошо.

и, если я готовлю оператор, а затем выполняю другие Query или Exec другие материалы, это тоже нормально ... просто не готовьте другой оператор, не закрывая предыдущий, и он выглядит нормально.

надеюсь, что это действительно проблема.

Благодарю.

Сможете ли вы создать небольшую программу на Go, с помощью которой можно будет воспроизвести ошибку?
Похоже, это определенно ошибка в драйвере, но не связанная с исходной проблемой, о которой здесь сообщается.
Пожалуйста, создайте новую проблему.

Думаю, проблема в этом:

package main

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, _ := sql.Open("mysql", "/")
    defer db.Close()
    tx, err := db.Begin()
    if err != nil {
        panic(err)
    }
    defer tx.Commit()
    stmt1, err := tx.Prepare("SELECT 1")
    if err != nil {
        panic(err)
    }
    rows1, err := stmt1.Query()
    if err != nil {
        panic(err)
    }
    stmt2, err := tx.Prepare("SELECT 2")
    if err != nil {
        // rows1 is not closed -> triggers busy buffer because transaction is on one connection
        // and stmt1, stmt2 use the same one.
        // Move rows1.Close() in front of tx.Prepare and it disappears
        panic(err)
    }
    rows2, err := stmt2.Query()
    if err != nil {
        panic(err)
    }
    rows1.Close()
    rows2.Close()
    stmt1.Close()
    stmt2.Close()
}

Я только что столкнулся с аналогичной проблемой загруженного буфера и могу подтвердить, что @arnehormann кажется правильным. Проблема возникает при попытке использовать одну и ту же транзакцию для нескольких запросов, пока объект строк все еще открыт.

Привет, ребята, я не знаю, решилась ли эта проблема каким-либо образом. Я вижу эту проблему в коротких вставках, выполненных с помощью "Exec" ->

var sql = "вставить в таблицу (f1, f2 ... f25) значения (?,?, ...?)"
_, ошибка: = db.Exec (sql, ...)

Примерно после 4000, иногда 5000 вставок я получаю «Unexpected EOF» и «Busy Buffer».
Вставки плотные (в цикле for), но между ними есть запрос REST, так что не так быстро; та же ссылка на подключение. Это Go 1.3.

Спасибо,
Сал

@Sal - что происходит, когда вы используете go 1.4?

В среду, 31 декабря 2014 г., в 22:11, Сал А. Магноун [email protected]
написал:

Привет, ребята, я не знаю, решилась ли эта проблема каким-либо образом. Я вижу это
выпуск в коротких вставках, выполненных с "Exec" ->

var sql = "вставить в таблицу (f1, f2 ... f25) значения (?,?, ...?)"
_, ошибка: = db.Exec (sql, ...)

Примерно после 4000, иногда 5000 вставок я получаю «Неожиданный EOF» и «Занято».
Буфер ».
Вставки плотные (в цикле for), но есть запрос REST между
друг, значит, не такой скоростной; та же ссылка на подключение. Это Go 1.3.

Спасибо,
Сал

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413.

Спасибо за ответ.

1.4 - та же ошибка. Умер на 4205 вставках примерно за 50 минут (между каждой вставкой есть ввод / вывод сети и экрана).

Я изменил код, чтобы можно было продолжить с того места, где он остановился в прошлый раз. Это не критично для этого приложения, но может быть критичным для других приложений в этом проекте, если это проблема совокупного запроса.

-Сал

От: carbocation [mailto: [email protected]]
Отправлено: Воскресенье, 4 января 2015 г., 9:50
Кому: go-sql-driver / mysql
Копия: Сал А. Магноне
Тема: Re: [mysql] Странная ошибка при разорванном соединении (# 185)

@Sal - что происходит, когда вы используете go 1.4?

В среду, 31 декабря 2014 г., в 22:11, Сал А. Магноун < [email protected] [email protected] >
написал:

Привет, ребята, я не знаю, решилась ли эта проблема каким-либо образом. Я вижу это
выпуск в коротких вставках, выполненных с "Exec" ->

var sql = "вставить в таблицу (f1, f2 ... f25) значения (?,?, ...?)"
_, ошибка: = db.Exec (sql, ...)

Примерно после 4000, иногда 5000 вставок я получаю «Неожиданный EOF» и «Занято».
Буфер ».
Вставки плотные (в цикле for), но есть запрос REST между
друг, значит, не такой скоростной; та же ссылка на подключение. Это Go 1.3.

Спасибо,
Сал

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68635254. https://github.com/notifications/beacon/AA4DdvfCFMdiqPlTZITEs9VrxyyJqqFQks5neUqigaJpZM4BSM1b.gif

Эта ветка сейчас превращается в несколько потоков? Следует ли помещать самые свежие комментарии в новый выпуск, а этот - закрывать?

@xaprb Я согласен, я думаю, что сейчас есть несколько тем. Мы, вероятно, сможем закрыть это и перенести https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413 в новый выпуск.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги