Google App EngineからCloud SQL (MySQL) を利用する方法

以前にGoogle App EngineからNo SQLであるGoogle Cloud Datastoreを利用する方法を紹介しましたが、当然のことながらRDBMSであるMySQLも利用することができます。Google Cloud PlatformでMySQLを利用するには、Cloud SQLを利用します。 ここではGoogle App Engine (Python 2.7) からCloud SQLの利用手順を紹介します。

環境の準備

ローカル環境においてPythonでMySQLを利用するには、MySQL-pythonが必要です。Windowsを利用している場合は、下記からダウンロード・インストールしてください。 https://www.codegood.com/downloads どれをダウンロードすればいいかわからない方でも、多くは64bit用で大丈夫でしょう。 MySQL-python-1.2.3.win-amd64-py2.7.exe

プロジェクトへの記述

プロジェクトの設定を行う app.yaml には、ライブラリとしてMySQLdbを利用すること、CloudSQLの必要項目の記述を行います。具体的には下記のように書きます。
application: xxxxxxxxxx
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /static
  static_dir: static
- url: /.*
  script: main.app

libraries:
- name: ssl
  version: latest
- name: MySQLdb
  version: latest

env_variables:
  CLOUDSQL_CONNECTION_NAME: xxxxxxxxxx:asia-northeast1:xxxx
  CLOUDSQL_USER: xxxx
  CLOUDSQL_PASSWORD: xxxxxxxxxx
「libraries」項目にMySQLdb (16, 17行目) を追加しています。また「env_variables」項目に接続名・ユーザ・パスワードを記述しています。

MySQLへの接続

私はローカル環境でテストするときは、ローカルで動作しているMySQLを利用しています。そのため、接続はGCP環境とローカル環境で次のように分けています。(全ソースコードは末尾に記します。)
import os
import MySQLdb

CLOUDSQL_CONNECTION_NAME = os.environ.get('CLOUDSQL_CONNECTION_NAME')
CLOUDSQL_USER = os.environ.get('CLOUDSQL_USER')
CLOUDSQL_PASSWORD = os.environ.get('CLOUDSQL_PASSWORD')


def connect_to_cloudsql():
    if os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine/'):
        cloudsql_unix_socket = os.path.join(
            '/cloudsql', CLOUDSQL_CONNECTION_NAME)

        db = MySQLdb.connect(
            unix_socket=cloudsql_unix_socket,
            user=CLOUDSQL_USER,
            passwd=CLOUDSQL_PASSWORD,
            charset="utf8")

    else:
        db = MySQLdb.connect(
            host='127.0.0.1',
            user=CLOUDSQL_USER,
            passwd=CLOUDSQL_PASSWORD,
            charset="utf8"
        )

    return db
CloudSQLに接続するには unix_socket の設定が必要になります。そのため11行目のように cloudsql_unix_socket を用意しています。

データ抽出

MySQLサーバへ接続できれば、あとは通常に利用方法と同じです。WebフレームワークFlaskで利用する一例を下記に記します。
@app.route('/mysql')
def mysql():
    db = connect_to_cloudsql()

    cursor = db.cursor()
    sql = 'SELECT * FROM papi.users'
    cursor.execute(sql)

    output = ''
    for row in cursor.fetchall():
        output += '{}\n'.format(row)

    db.close()

    return output
先程の接続情報を db 変数を用い、cursorを取得します。 クエリ文を実行するにはexecuteメソッドを実行します。実行結果を取得するにはfetchallメソッドを用います。 そして最後に db 変数に対してcloseメソッドを実行してください。

注意

Flaskで利用する場合、間違っても db 変数をグローバル変数にしないでください。1つ1つのリクエストに対して db 変数を用意しないと、同時に複数のリクエストが発生したときエラーになります。

まとめ

Google App EngineでCloud SQL (MySQL) を利用する場合、app.yaml の libraries 項目に MySQLdb を記述します。また unix_socket に接続先を設定します。これだけで普段通りにMySQLを扱うことができます。

main.py

# coding: UTF-8
import os
from flask import Flask
import MySQLdb

app = Flask(__name__, static_url_path='/static')

CLOUDSQL_CONNECTION_NAME = os.environ.get('CLOUDSQL_CONNECTION_NAME')
CLOUDSQL_USER = os.environ.get('CLOUDSQL_USER')
CLOUDSQL_PASSWORD = os.environ.get('CLOUDSQL_PASSWORD')


def connect_to_cloudsql():
    """
    Cloud SQLへ接続
    :return: コネクション
    """
    if os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine/'):
        cloudsql_unix_socket = os.path.join(
            '/cloudsql', CLOUDSQL_CONNECTION_NAME)

        db = MySQLdb.connect(
            unix_socket=cloudsql_unix_socket,
            user=CLOUDSQL_USER,
            passwd=CLOUDSQL_PASSWORD,
            charset="utf8")

    else:
        db = MySQLdb.connect(
            host='127.0.0.1',
            user=CLOUDSQL_USER,
            passwd=CLOUDSQL_PASSWORD,
            charset="utf8"
        )

    return db


@app.route('/mysql')
def mysql():
    """
    Cloud SQLへの接続テスト
    :return:
    """
    db = connect_to_cloudsql()

    cursor = db.cursor()
    sql = 'SELECT * FROM papi.users'
    cursor.execute(sql)

    output = ''
    for row in cursor.fetchall():
        # print(row[1])
        output += '{}\n'.format(row)

    db.close()

    return output
» エンジニア登録はこちら