Cloud SQL with Go-MySQL-Driver

770 views
Skip to first unread message

Julien Schmidt

unread,
Oct 26, 2013, 2:24:38 PM10/26/13
to google-ap...@googlegroups.com
We would like to add support for Cloud SQL to github.com/go-sql-driver/mysql. We are wondering if additional work is required.
Since we are not AppEngine users, we depend on your help.

Looking at the documentation for Python and PHP, the following Unix Domain Socket seems to work:
/cloudsql/your-project-id:your-instance-name

Therefore the following should work with Go-MySQl-Driver:
db, err := sql.Open("mysql", "username:password@unix(/cloudsql/your-project-id:your-instance-name)/dbname")

Can anyone confirm that this works (or not)?


Moreover I hope someone from the Go (appengine) team can tell me how this differs from appengine/cloudsql from the SDK.
Does this also just Dial the Unix Domain Socket?

David Symonds

unread,
Oct 27, 2013, 12:04:35 AM10/27/13
to Julien Schmidt, google-appengine-go
There shouldn't be much to do. The appengine/cloudsql package [1]
provides a Dial function that takes a CloudSQL instance name and
returns a net.Conn; you just have to arrange for your mysql driver to
call that (or have some way of taking a net.Conn).

You could follow what we did for ziutek's mymysql package [2].


[1] https://developers.google.com/appengine/docs/go/cloud-sql/reference
[2] https://github.com/ziutek/mymysql/commit/916a88016dee9e65e337f53bfb3a7a2456a5b11b

Ugorji Nwoke

unread,
Oct 30, 2013, 2:43:03 PM10/30/13
to google-ap...@googlegroups.com

Julien Schmidt

unread,
Nov 16, 2013, 9:27:49 AM11/16/13
to google-ap...@googlegroups.com, Julien Schmidt
Thanks to a patch contributed by Leonardo YongUk Kim, we now have Cloud SQL support via the AppEngine SDK in the master branch (not in the 'go get' version yet).
Use the following DSN for connecting: user@cloudsql(project-id:instance-name)/dbname

We would appreciate feedback if you encounter any problems. 

elicri...@gmail.com

unread,
Feb 19, 2014, 5:42:32 PM2/19/14
to google-ap...@googlegroups.com, Julien Schmidt
When i use "github.com/go-sql-driver/mysql" and try to connect to my cloudsql instance with 
db, err := sql.Open("mysql", "user@cloudsql(project-id:instance-name)/dbname")

i get the error:
2014/02/19 22:40:33 http: panic serving 127.0.0.1:60770: cloudsql: not supported in dev yet
goroutine 6 [running]:

Any ideas?

Eli Criffield

unread,
Feb 19, 2014, 5:44:37 PM2/19/14
to google-ap...@googlegroups.com, Julien Schmidt
When i use "github.com/go-sql-driver/mysql" and try to connect to my cloudsql instance with 
db, err := sql.Open("mysql", "user@cloudsql(project-id:instance-name)/dbname")

i get the error:
2014/02/19 22:40:33 http: panic serving 127.0.0.1:60770: cloudsql: not supported in dev yet
goroutine 6 [running]:

Any ideas?

On Saturday, November 16, 2013 8:27:49 AM UTC-6, Julien Schmidt wrote:

Eli Criffield

unread,
Feb 28, 2014, 11:48:36 AM2/28/14
to google-ap...@googlegroups.com, Julien Schmidt
just to follow up if i upload to appengine i get.

panic: runtime error: invalid memory address or nil pointer dereference

Julien Schmidt

unread,
Jun 4, 2014, 4:19:48 PM6/4/14
to google-ap...@googlegroups.com, g...@julienschmidt.com
We released v1.2 of the driver, wich includes he Cloud SQL support, yesterday. Also we removed the go1 tag which caused a lot of confusion.
You should now get the lastest version via go get which should include proper support for Cloud SQL on App Engine.

Please let us know if there are still any problems.

Ronoaldo Pereira

unread,
Jun 6, 2014, 11:20:54 PM6/6/14
to google-ap...@googlegroups.com, g...@julienschmidt.com
Hi folks,

I'm trying to use the go-sql-driver/mysql from AppEngine to connect to a regular MySQL server, and use that server. The problem is that, when the connection is attempted, I receive a permission error. Reading more about how App Engine allows outbound sockets, I discovered that the net.Conn that is allowed is the one returned by the appengine/socket API.

I'm trying to implement a dialer that uses the appengine/socket package to be registered using the mysql.RegisterDial func, but the problem is how do I pass a different appengine.Context for each request to the driver? Any toughts?

We only managed to get this working by making a copy of the database/sql package into our app, and adding a new "Open" method that receives the AppEngine context, and that uses a version of the go-sql-driver/mysql package that uses the appengine/socket.Dial function instead of a regular Dial function. Does this have any implications, for instance, when used concurrently by different requests?

Regards,

Julien Schmidt

unread,
Jun 7, 2014, 7:14:48 AM6/7/14
to google-ap...@googlegroups.com
On Saturday, June 7, 2014 5:20:54 AM UTC+2, Ronoaldo Pereira wrote:
I'm trying to use the go-sql-driver/mysql from AppEngine to connect to a regular MySQL server, and use that server.
That's probably a bad idea. It will be slow and tricky to implement (as you already noticed). 


I'm trying to implement a dialer that uses the appengine/socket package to be registered using the mysql.RegisterDial func, but the problem is how do I pass a different appengine.Context for each request to the driver? Any toughts?
I am not an appengine user, so I'm not used to appengine.Contexts and can't test it. But as far as I understand the documentation, a Context is bound to a http.Request. So after the http.Request in which the mysql connection was opened is finished, the connection would be invalid. One could try to set a new context, but this will be near to impossible, since the database/sql package wraps the driver connection and it is therefore not possible to associate the underlying net.Conn.

The other option that could maybe (probably not) work, is creating your own http.Request instead of using an incoming user request:
mysql.RegisterDial("ae-tcp", func(addr string) (net.Conn, error) {
// Cheat and generate a new request
req, err := http.NewRequest("GET", "/random/path/1234", nil)
if err != nil {
return err // damn!
}
ctx := appengine.NewContext(req)
return socket.Dial(ctx, "tcp", addr)
})

Then use it with:
sql.Open("mysql", "user:pw@ae-tcp(host:port)/mydb?some=parameters")
 

We only managed to get this working by making a copy of the database/sql package into our app, and adding a new "Open" method that receives the AppEngine context, and that uses a version of the go-sql-driver/mysql package that uses the appengine/socket.Dial function instead of a regular Dial function. Does this have any implications, for instance, when used concurrently by different requests?
I don't know your implementation, but most probably: YES! 


Maybe someone other has an idea how to solve this. In my estimation the effort won't be worth it.

mkvir...@gmail.com

unread,
Jan 5, 2015, 6:29:08 AM1/5/15
to google-ap...@googlegroups.com
I tried the driver and got the following error: "driver: bad connection".
Did I miss something?

This is a snapshot of my code:

import (
"database/sql"
"fmt"
"net/http"
)

func Handler(w http.ResponseWriter, r *http.Request) {
db, dbErr := sql.Open("mysql", "myapp@cloudsql(myproject:myinstance)/mydb")
if dbErr != nil {
fmt.Fprintf(w, "open err\n")
http.Error(w, dbErr.Error(), 500)
return
}
defer db.Close()

// Open doesn't open a connection. Validate DSN data:
pingErr := db.Ping()
if pingErr != nil {
fmt.Fprintf(w, "ping err\n")
http.Error(w, pingErr.Error(), 500)
return
}
fmt.Fprint(w, "db test ok!\n")

rows, rowErr := db.Query("SELECT iduserInfo, userName FROM userInfo")
if rowErr != nil {
fmt.Fprintf(w, "Query err\n")
http.Error(w, rowErr.Error(), 500)
return
}
defer rows.Close()

for rows.Next() {
var (
userID   int
userName string
)
if err := rows.Scan(&userID, &userName); err != nil {
http.Error(w, err.Error(), 500)
}
fmt.Fprintf(w, "%d is %s\n", userID, userName)
}

if err := rows.Err(); err != nil {
http.Error(w, err.Error(), 500)
}
}

Julien Schmidt於 2013年10月27日星期日UTC+8上午2時24分38秒寫道:

Stanley Iriele

unread,
Oct 1, 2015, 1:06:33 AM10/1/15
to google-appengine-go, mkvir...@gmail.com

Yeah....I get:

Error 1044: Access denied for user ''@'localhost' to database

This clearly does not work with appengine. When making requests it does but from appengine...nope

Derek Perkins

unread,
Oct 1, 2015, 4:57:41 PM10/1/15
to google-appengine-go
Are you on classic App Engine or Managed VMs?

Stanley Iriele

unread,
Oct 1, 2015, 5:20:55 PM10/1/15
to Derek Perkins, google-appengine-go
Classic...but I figured out the problem. In appengine YOU MUST USE THE ROOT USER. no other use works at all...thanks though

On Thu, Oct 1, 2015 at 1:57 PM, Derek Perkins <de...@derekperkins.com> wrote:
Are you on classic App Engine or Managed VMs?

--
You received this message because you are subscribed to a topic in the Google Groups "google-appengine-go" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-appengine-go/XZwBvrFCrQs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-appengin...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages