Go поставляется с библиотекой database / sql для взаимодействия с любой реляционной базой данных. В попытке абстрагироваться от некоторых низкоуровневых сложностей при подключении к базе данных и управлении пулом соединений, открытые API-интерфейсы, похоже, делают немного больше, чем вы на самом деле ожидаете. В конечном итоге это приводит к некоторой путанице в том, как использовать эти API.

Поэтому я попытался проанализировать поведение основных API, о которых нужно знать перед их использованием.

Я провел свои эксперименты с моим приложением go, запущенным на виртуальном компьютере (ubuntu) и сервером mysql на моем хост-компьютере.

Запрос выполнен: вставьте в элементы (название, цена, описание) значения («домовой», 240, «шипящий»)

Запрос

Мы всегда должны использовать db.Query всякий раз, когда мы хотим сделать выбор, и мы никогда не должны игнорировать возвращенные строки Query, а перебирать их (иначе мы утечка соединения БД!)

Выполнение Query (query) не будет использовать подготовленный оператор (см. Снимок wirehark ниже).

  • Обратите внимание, что от клиента к серверу был отправлен только 1 TCP-запрос (без входа в систему)
  • Соединение будет автоматически выпущено в пул при повторении возвращаемых строк, или мы можем явно вызвать rows.Close (), когда мы закончим.
  • Использование - db.Query («вставьте в элементы (название, цена, описание) значения (« домовой », 240,« шипящий »)»)

Выполнение Query (queryTemplate, params) будет использовать подготовленный оператор скрытых.

  • Обратите внимание, что от клиента к серверу было отправлено 3 запроса TCP (без входа в систему)
  • Соединение будет автоматически выпущено в пул при повторении возвращаемых строк, или мы можем явно вызвать rows.Close (), когда мы закончим.
  • Использование - db.Query («вставить в элементы (название, цена, описание) значения (?,?,?)», «Пирожное», 240, «шипящий»)

Exec

Мы всегда должны использовать db.Exec всякий раз, когда мы хотим выполнить вставку, обновление или удаление.

Выполнение Exec (query) не будет использовать подготовленный оператор, поэтому меньшее количество вызовов TCP к серверу SQL

  • Обратите внимание, что от клиента к серверу был отправлен только 1 TCP-запрос (без входа в систему)
  • Автоматически освобождает соединение с пулом.
  • Использование - db.Exec («вставить в элементы (название, цена, описание) значения (« домовой », 240,« шипящий »)»)

Выполнение Exec (queryTemplate, params) будет использовать заранее подготовленный оператор, поэтому количество TCP-вызовов к серверу SQL будет увеличиваться.

  • Обратите внимание, что от клиента к серверу было отправлено 3 запроса TCP (без входа в систему)
  • Автоматически освобождает соединение с пулом.
  • Использование - db.Exec («вставить в элементы (название, цена, описание) значения (?,?,?)», «Пирожное», 240, «шипящий»)

Подготовить

Это следует использовать только тогда, когда мы хотим подготовиться один раз в начале программы и выполнить N раз в течение программы.

  • Обратите внимание, что от клиента к серверу было отправлено 2 запроса TCP (без входа в систему).
  • Нам нужно явно закрыть оператор, если он нам больше не нужен. Иначе нам не удастся освободить выделенные ресурсы как на клиенте, так и на сервере!
  • Использование - stmt.Exec («вставить в элементы (название, цена, описание) значения (?,?,?)», «Пирожное», 240, «шипящий»)

Заключение

Одна из основных проблем, с которыми мы столкнулись при первом использовании этого пакета sql, заключалась в том, что мы на самом деле не знали, что он создает подготовленные операторы под ним, даже когда мы не указывали это явно.

Надеюсь, приведенные выше пункты прояснят, когда вызываются подготовленные операторы и как их избежать.