我正在尝试使用 pymysql 进行连接,使用的代码非常接近文档中提供的示例:https://cloud.google.com/functions/docs/sql#functions_sql_mysql-python
数据库有公共IP,没有授权网络(因为cf应该使用套接字(,我的用户创建允许从任何地方访问。
使用Cloud SQL Proxy在本地运行工作正常,但是在Google Cloud上,我的连接被拒绝。
编辑:更新了示例,其中包含使用 env vars 在本地运行的代码
import logging
import os
import pymysql
from pymysql.err import OperationalError
mysql_conn = None
def __get_cursor():
try:
return mysql_conn.cursor()
except OperationalError:
mysql_conn.ping(reconnect=True)
return mysql_conn.cursor()
def get_config():
return {
'unix_socket': f'/cloudsql/{os.environ["CONNECTION_NAME"]}',
'user': os.environ['DB_USER'],
'password': os.environ['DB_PASSWORD'],
'db': os.environ['DB_NAME'],
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor,
'autocommit': True
}
def mysql_demo(request):
global mysql_conn
if not mysql_conn:
mysql_config = get_config()
logging.info('Open db with config: %s', mysql_config)
try:
mysql_conn = pymysql.connect(**mysql_config)
except OperationalError as exception:
logging.warning('Unable to get db connection: %s', str(exception))
return
with __get_cursor() as cursor:
cursor.execute('SELECT NOW() as now')
results = cursor.fetchone()
return str(results['now'])
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
os.environ['CONNECTION_NAME'] = 'my-project:us-central1:cf-test'
os.environ['DB_USER'] = 'db-user'
os.environ['DB_PASSWORD'] = 'db-password'
os.environ['DB_NAME'] = 'db_name'
logging.info(mysql_demo(None))
编辑:附加输出
在本地运行时,这将打印出来:
INFO:root:2019-09-24 07:11:54
当作为云函数运行时,我得到输出:">
2019-09-24 09:14:59.279 CEST test-cloud-sql mesuju89uxuw Open db with config: {'unix_socket': '/cloudsql/boeingfda-jal:us-central1:cf-test', 'user': 'enplore', 'password': 'az2labha', 'db': 'content_enplore_auth', 'charset': 'utf8mb4', 'cursorclass': <class 'pymysql.cursors.DictCursor'>, 'autocommit': True}
2019-09-24 09:14:59.856 CEST test-cloud-sql mesuju89uxuw Unable to get db connection: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
如果您发布收到的错误,通常会更有帮助,因为它通常会提供额外的上下文。以下是一些可能的原因:
- 确保已启用云 SQL 管理员 API。
- 验证您用于运行实例的服务账户(默认为
service-[YOUR_PROJECT_NUMBER]@gcf-admin-robot.iam.gserviceaccount.com
(是否具有正确的 IAM 权限(Cloud SQL Client
角色或cloudsql.instances.connect
和cloudsql.instances.get
权限(。 - 最后,验证
CONNECTION_NAME
变量是否拼写错误。
最后,应考虑使用连接池(如 SQLAlchemy(并将最大限制设置为 1。连接池将更优雅地处理错误,并限制每个实例使用的连接数。
看起来您的unix_socket条目未正确生成。它接受以下格式的数据:
'/cloudsql/project-id:region:instance-name'
例:
'/cloudsql/my-awesome-project:us-central1:mysqlinst1'
若要获取确切的连接名称,可以使用以下命令:
gcloud sql instances describe <instance_name> | grep connectionName