Using Cloud SQL for MySQL

This page shows how to connect to a Cloud SQL for MySQL Second Generation instance from an App Engine application, and how to read and write to Cloud SQL. Cloud SQL is a SQL database that lives in Google's cloud.

To learn more about Cloud SQL, see the Cloud SQL documentation. For information on Cloud SQL pricing and limits, see the Cloud SQL Pricing page. App Engine applications are also subject to the App Engine quotas.

Before you begin

  1. Create or select a GCP project in the GCP Console and then ensure that project includes an App Engine application and billing is enabled:
    Go to App Engine

    The Dashboard opens if an App Engine application already exists in your project and billing is enabled. Otherwise, follow the prompts for choosing a region and enabling billing.

  2. Enable the Cloud SQL API.

    Enable the API

  3. To deploy your app with the gcloud tool, you must download, install, and initialize the Cloud SDK:
    Download the SDK

    If you already have the gcloud tool installed and want to configure it to use a GCP project ID other than the one that you initialized it to, see Managing Cloud SDK Configurations.

Configuring the Cloud SQL instance

To create and configure a Cloud SQL instance:

  1. Create a Cloud SQL Second Generation instance.
  2. If you haven't already, set the password for the default user on your Cloud SQL instance:
    gcloud sql users set-password root --host=% --instance [INSTANCE_NAME] --password [PASSWORD]
    
  3. If you don't want to use the default user to connect, create a user.
  4. Record the connection name for the instance:
    gcloud sql instances describe [INSTANCE_NAME]
    

    For example:

    connectionName: project1:us-central1:instance1
    

    You can also find this value in the Instance details page of the Google Cloud Platform Console.

  5. Create a database on your Cloud SQL instance.
    gcloud sql databases create [DATABASE_NAME] --instance=[INSTANCE_NAME]
    
    For more information on creating and managing databases, see the Cloud SQL documentation.

Setting up your local environment

Once deployed, your application uses the Cloud SQL Proxy that is built in to the App Engine runtime environment to communicate with your Cloud SQL instance. However, to test your application locally, you must install and use a local copy of the Cloud SQL Proxy in your development environment.

To perform basic administrative tasks on your Cloud SQL instance, you can use the administration client for your database or the GCP Console.

  1. Authenticate the gcloud tool to use the proxy to connect from your local machine:

    gcloud auth application-default login
    
  2. Install the Cloud SQL proxy:

    Linux 64-bit

    1. Download the proxy:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
      
    2. Make the proxy executable:
      chmod +x cloud_sql_proxy
      

    Linux 32-bit

    1. Download the proxy:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.386 -O cloud_sql_proxy
      
    2. Make the proxy executable:
      chmod +x cloud_sql_proxy
      

    macOS 64-bit

    1. Download the proxy:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
      
    2. Make the proxy executable:
      chmod +x cloud_sql_proxy
      

    macOS 32-bit

    1. Download the proxy:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.386
      
    2. Make the proxy executable:
      chmod +x cloud_sql_proxy
      

    Windows 64-bit

    Right-click https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe and select "Save link as..." to download the proxy, renaming it to cloud_sql_proxy.exe.

    Windows 32-bit

    Right-click https://dl.google.com/cloudsql/cloud_sql_proxy_x86.exe and select "Save link as..." to download the proxy, renaming it to cloud_sql_proxy.exe.
    If your operating system is not included here, you can also compile the proxy from source.

  3. Run the proxy:

    Depending on your language and environment, you can start the proxy using either TCP sockets or Unix sockets.

    TCP sockets

    1. Copy your instance connection name from the Instance details page.
    2. If you are using a service account to authenticate the proxy, note the location on your client machine of the private key file that was created when you created the service account.
    3. Start the proxy.

      Some possible proxy invocation strings:

      • Using Cloud SDK authentication:
        ./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:3306
        
        The specified port must not already be in use, for example, by a local database server.
      • Using a service account and explicit instance specification (recommended for production environments):
        ./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:3306 \
                          -credential_file=<PATH_TO_KEY_FILE> &
        

      For more information about proxy options, see Options for authenticating the proxy and Options for specifying instances.

    Unix sockets

    1. If you are using explicit instance specification, copy your instance connection name from the Instance details page.
    2. Create the directory where the proxy sockets will live:
      sudo mkdir /cloudsql; sudo chmod 777 /cloudsql
    3. If you are using a service account to authenticate the proxy, note the location on your client machine of the private key file that was created when you created the service account.
    4. Open a new terminal window and start the proxy.

      Some possible proxy invocation strings:

      • Using a service account and explicit instance specification (recommended for production environments):
        ./cloud_sql_proxy -dir=/cloudsql -instances=<INSTANCE_CONNECTION_NAME> \
                          -credential_file=<PATH_TO_KEY_FILE> &
      • Using Cloud SDK authentication and automatic instance discovery:
        ./cloud_sql_proxy -dir=/cloudsql &

      It is best to start the proxy in its own terminal so you can monitor its output without it mixing with the output from other programs.

      For more information about proxy options, see Options for authenticating the proxy and Options for specifying instances.

  4. To use the administration client, you can install a local copy and connect either by using the proxy or IP Addresses.

    For more information, see Connecting MySQL Client Using the Cloud SQL Proxy and Connecting MySQL Client Using IP Addresses.

Setting connection strings and adding a library

  1. Set up the local environment to support connections for local testing.

    For example, for the provided code sample:

    export CLOUDSQL_CONNECTION_NAME=INSTANCE_CONNECTION_NAME
    export CLOUDSQL_USER=USER
    export CLOUDSQL_PASSWORD=PASSWORD
    

  2. To allow your app to connect to your Cloud SQL instance when the app is deployed, add the user, password, database, and instance connection name variables from Cloud SQL to the related environment variables in the app.yaml file:

    runtime: go111
    
    env_variables:
      # Replace INSTANCE_CONNECTION_NAME with the value obtained when configuring your
      # Cloud SQL instance, available from the Google Cloud Console or from the Cloud SDK.
      # For Cloud SQL 2nd generation instances, this should be in the form of "project:region:instance".
      CLOUDSQL_CONNECTION_NAME: INSTANCE_CONNECTION_NAME
      # Replace username and password if you aren't using the root user.
      CLOUDSQL_USER: root
      CLOUDSQL_PASSWORD: password
    

  3. Download a MySQL package to your local machine using the command line. For example:

    go get -u github.com/go-sql-driver/mysql
    

Running the sample code

// Sample cloudsql demonstrates connection to a Cloud SQL instance from App Engine standard.
package main

import (
	"bytes"
	"database/sql"
	"fmt"
	"log"
	"net/http"
	"os"

	// MySQL library, comment out to use PostgreSQL.
	_ "github.com/go-sql-driver/mysql"
	// PostgreSQL Library, uncomment to use.
	// _ "github.com/lib/pq"
)

var db *sql.DB

func main() {
	db = DB()

	http.HandleFunc("/", indexHandler)
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("Defaulting to port %s", port)
	}

	log.Printf("Listening on port %s", port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

// DB gets a connection to the database.
// This can panic for malformed database connection strings, invalid credentials, or non-existance database instance.
func DB() *sql.DB {
	var (
		connectionName = mustGetenv("CLOUDSQL_CONNECTION_NAME")
		user           = mustGetenv("CLOUDSQL_USER")
		password       = os.Getenv("CLOUDSQL_PASSWORD") // NOTE: password may be empty
		socket         = os.Getenv("CLOUDSQL_SOCKET_PREFIX")
	)

	// /cloudsql is used on App Engine.
	if socket == "" {
		socket = "/cloudsql"
	}

	// MySQL Connection, comment out to use PostgreSQL.
	// connection string format: USER:PASSWORD@unix(/cloudsql/)PROJECT_ID:REGION_ID:INSTANCE_ID/[DB_NAME]
	dbURI := fmt.Sprintf("%s:%s@unix(%s/%s)/", user, password, socket, connectionName)
	conn, err := sql.Open("mysql", dbURI)

	// PostgreSQL Connection, uncomment to use.
	// connection string format: user=USER password=PASSWORD host=/cloudsql/PROJECT_ID:REGION_ID:INSTANCE_ID/[ dbname=DB_NAME]
	// dbURI := fmt.Sprintf("user=%s password=%s host=/cloudsql/%s dbname=%s", user, password, connectionName)
	// conn, err := sql.Open("postgres", dbURI)

	if err != nil {
		panic(fmt.Sprintf("DB: %v", err))
	}

	return conn
}

// indexHandler responds to requests with our list of available databases.
func indexHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}

	w.Header().Set("Content-Type", "text/plain")

	rows, err := db.Query("SHOW DATABASES")
	if err != nil {
		log.Printf("Could not query db: %v", err)
		http.Error(w, "Internal Error", 500)
		return
	}
	defer rows.Close()

	buf := bytes.NewBufferString("Databases:\n")
	for rows.Next() {
		var dbName string
		if err := rows.Scan(&dbName); err != nil {
			log.Printf("Could not scan result: %v", err)
			http.Error(w, "Internal Error", 500)
			return
		}
		fmt.Fprintf(buf, "- %s\n", dbName)
	}
	w.Write(buf.Bytes())
}

func mustGetenv(k string) string {
	v := os.Getenv(k)
	if v == "" {
		log.Panicf("%s environment variable not set.", k)
	}
	return v
}

Testing and deploying

  1. To test your application locally:

    go run cloudsql.go
    

  2. After local testing, deploy your app to App Engine:

    gcloud app deploy
    

  3. To launch your browser and view the app at http://[YOUR_PROJECT_ID].appspot.com, run the following command:

    gcloud app browse
    

Running Cloud SQL and App Engine in separate projects

If your App Engine application and Cloud SQL instance are in different Google Cloud Platform projects, you must use a service account to allow your App Engine application access to Cloud SQL.

This service account represents your App Engine application and is created by default when you create a Google Cloud Platform project.

  1. If your App Engine application is in the same project as your Cloud SQL instance, you can skip this section and go to Setting up your local environment. Otherwise, proceed to the next step.
  2. Identify the service account associated with your App Engine application. The default App Engine service account is named [PROJECT-ID]@appspot.gserviceaccount.com.

    You can verify the App Engine service account on the IAM Permissions page. Ensure that you select the project for your App Engine application, not your Cloud SQL instance.

    Go to the IAM Permissions page

  3. Go to the IAM & Admin Projects page in the Google Cloud Platform Console.

    Go to the IAM & Admin Projects page

  4. Select the project that contains the Cloud SQL instance.
  5. Search for the service account name.
  6. If the service account is already there, and it has a role that includes the cloudsql.instances.connect permission, you can proceed to Setting up your local environment.

    The Cloud SQL Client, Cloud SQL Editor and Cloud SQL Admin roles all provide the necessary permission, as do the legacy Editor and Owner project roles.

  7. Otherwise, add the service account by clicking Add.
  8. In the Add members dialog, provide the name of the service account and select a role that include the cloudsql.instances.connect permission (any Cloud SQL predefined role other than Viewer will work).

    Alternatively, you can use the primitive Editor role by selecting Project > Editor, but the Editor role includes permissions across Google Cloud Platform.

    If you do not see these roles, your Google Cloud Platform user might not have the resourcemanager.projects.setIamPolicy permission. You can check your permissions by going to the IAM page in the Google Cloud Platform Console and searching for your user id.

  9. Click Add.

    You should now see the service account listed with the specified role.

Was this page helpful? Let us know how we did:

Send feedback about...

App Engine standard environment for Go 1.11 docs