我有一些在本地GAE服务器上运行的代码,但是一旦将其发布到GAE,它就会引发错误"驱动程序:连接错误"。

下面的代码生成一个新的* sql.DB:

1
2
3
4
5
6
7
8
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中,我有以下内容:

1
2
3
env_variables:
  dbcloud: 'projectid:instancename'
  dblocal: 'xxx.xxx.xxx.xxx'

看来正确返回了一个新的* sql.DB,但是一旦我开始使用准备好的语句,事情就会开始崩溃。

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

我已经为此战斗了一个小时,我可能正在做一些非常愚蠢的事情,任何帮助将不胜感激!

  • 您是否正在使用go-sql-driver("github.comgo-sql-drivermysql")或mymysql驱动程序("github.comziutekmymysqlgodrv")?
  • github.com/go-sql??-driver/mysql,我需要在GAE中使用github.com/ziutek??/mymysql/godrv吗?
  • 不,两者都可以与Cloud SQL一起很好地工作,但是它们需要不同的语法来定义数据源。但是,您看起来不错,您确定用户为root,并且项目ID和实例名称正确吗?
  • 是的,只有当前用户是root用户(我使用本地GAE服务器通过IP连接到Cloud SQL实例,并且运行良好),并且已经多次检查项目ID /实例名称,它们相同,所以我看不到是问题所在。
  • 您的应用程序和Cloud SQL实例是否位于同一区域?您是否已授予应用访问SQL实例的权限?
  • 是的,它们都是我们中心的,并且它们都在同一个项目中,因此我认为它们默认情况下具有访问权限,这脱离了SQL实例的访问控制:" App Engine授权默认情况下,该项目中的所有应用程序都经过授权。要在其他项目,请按照以下步骤操作。"
  • 请参阅此页面如何授予访问权限:从Google App Engine连接(注意:第一代和第二代实例的不同步骤)。
  • 是的,我已经看到,在询问这里我当前正在使用Gen 2之前,第一步是:"如果您的应用程序与Cloud SQL实例位于同一项目中,则可以继续执行步骤2。"哪一个给您连接代码?我唯一不了解的是sql.Open不会导致错误,但是之后尝试使用db会吗?
  • 那很正常。 sql.Open()仅验证其参数,但不会打开连接。为此,您可以使用DB.Ping()。有关详细信息,请参见以下答案:为什么sql.Open()不应返回nil作为错误?
  • 嘿@icza发现了问题!我需要将dbcloud env_variable更改为包括我的区域,即使它们都在us_central中?因此,现在它进入了projectid:regionname:instancename并可以工作了……非常感谢您的宝贵时间,尽管这对我来说只是一个愚蠢的错误!
  • 很高兴您解决了您的问题。请发布您的解决方案作为答案,以便其他人可以从中受益。

我最终需要更改我的dbcloud变量,以包括从以下位置将其更改的SQL Server的区域:

1
'projectid:instancename'

至:

1
'projectid:regionname:instancename'

不知道为什么我需要这样做,因为它不在https://github.com/go-sql-driver/mysql的文档中,但现在都可以使用!