Google App Engine Golang, драйвер: плохое соединение

У меня есть код, который работает на локальном сервере GAE, но как только я публикую его на GAE, он выдает ошибку «драйвер: плохое соединение».

Ниже код генерирует новый *sql.DB:

func NewDb() (*sql.DB, error) {
  cloud := os.Getenv("dbcloud")
  local := os.Getenv("dblocal")
  if appengine.IsDevAppServer() {
    return sql.Open("mysql", "root@tcp("+local+":3306)/dbo")
  }
  return sql.Open("mysql", "root@cloudsql("+cloud+")/dbo")
}

В моем app.yaml у меня есть следующее:

env_variables:
  dbcloud: 'projectid:instancename'
  dblocal: 'xxx.xxx.xxx.xxx'

Кажется, он правильно возвращает новый *sql.DB, но как только я начинаю использовать подготовленные операторы, все начинает ломаться.

db, err := NewDb() // err is nil
stmt, err := db.Prepare("INSERT INTO dbo.Users (Id) VALUES (?)") // err is driver: bad connection

Я боролся с этим уже час, и я, вероятно, делаю что-то очень глупое, любая помощь будет оценена по достоинству!


person lflahive    schedule 15.08.2016    source источник
comment
Вы используете драйвер go-sql ("github.com/go-sql-driver/mysql") или драйвер mymysql ("github.com/ziutek/mymysql/godrv")?   -  person icza    schedule 15.08.2016
comment
github.com/go-sql‌​-driver/mysql, нужно ли мне использовать github.com/ziutek‌​/mymysql/godrv с GAE?   -  person lflahive    schedule 15.08.2016
comment
Нет, оба они хорошо работают с Cloud SQL, но требуют разного синтаксиса для определения источника данных. Однако ваш выглядит нормально, вы уверены, что пользователь root, а идентификатор проекта и имя экземпляра верны?   -  person icza    schedule 15.08.2016
comment
Да, только пользователь в настоящее время является пользователем root (я подключаюсь к экземпляру Cloud SQL через IP, используя локальный сервер GAE, и он работает нормально) и несколько раз проверял идентификатор проекта / имя экземпляра, они идентичны, поэтому я не вижу, что это проблема.   -  person lflahive    schedule 15.08.2016
comment
Ваше приложение и экземпляр Cloud SQL находятся в одном регионе? Вы предоставили своему приложению доступ к экземпляру SQL?   -  person icza    schedule 15.08.2016
comment
Да, оба являются центральными для нас, и они находятся в одном и том же проекте, поэтому у них есть доступ по умолчанию, я полагаю, выходя из контроля доступа экземпляра SQL: Авторизация App Engine Все приложения в этом проекте авторизованы по умолчанию. Чтобы авторизовать приложения в других проектах, выполните следующие действия.   -  person lflahive    schedule 15.08.2016
comment
См. эту страницу, как предоставить доступ: Подключение из Google App Engine ( примечание: разные шаги для экземпляров первого и второго поколения).   -  person icza    schedule 15.08.2016
comment
Да, я видел это, прежде чем спросить здесь, я в настоящее время использую Gen 2, и первый шаг: если ваше приложение находится в том же проекте, что и ваш экземпляр Cloud SQL, вы можете перейти к шагу 2. который просто дает вам код подключения? Единственное, чего я не понимаю, это то, что sql.Open не вызывает ошибки, но попытка использовать db впоследствии вызывает?   -  person lflahive    schedule 16.08.2016
comment
Это нормально. sql.Open() просто проверяет свои аргументы, но не открывает соединение. Для этого вы можете использовать DB.Ping(). Подробнее см. в этом ответе: Почему sql.Open() возвращает nil как ошибку, хотя этого не должно быть?   -  person icza    schedule 16.08.2016
comment
Эй, @icza нашел проблему! Мне нужно было изменить переменную dbcloud env_variable, чтобы включить мой регион, хотя они оба находятся в us_central? Так что теперь он идет 'projectid:regionname:instancename' и работает... Большое спасибо за ваше время, хотя это была просто глупая ошибка с моей стороны!   -  person lflahive    schedule 16.08.2016
comment
Рад, что вы решили свою проблему. Пожалуйста, опубликуйте свое решение в качестве ответа, чтобы другие могли извлечь из него пользу.   -  person icza    schedule 16.08.2016


Ответы (1)


В итоге мне пришлось изменить мою переменную dbcloud, чтобы включить регион SQL-сервера, который изменил ее:

'projectid:instancename'

To:

'projectid:regionname:instancename'

Не знаю, зачем мне это нужно, поскольку этого нет в документах https://github.com/go-sql-driver/mysql, но теперь все работает!

person lflahive    schedule 16.08.2016