In Function Compute, execution instances are stateless. You can use a database to persist structured data and share state. By accessing a cloud database from Function Compute, you can perform operations such as data queries and insertions. This topic uses a Python function as an example to describe how to access an ApsaraDB RDS for MySQL instance from within the same VPC or across different VPCs and regions.
Prerequisites
-
The
index.pysample code in this topic queries all data from a table namedusers. You can modify the table name as needed, but ensure that the table contains at least one record.
Procedure
Step 1: Configure the database whitelist
Scenario 1: Same VPC
If you access a database in the same VPC, ensure that the database instance and the function are in the same region. We recommend that you create the database instance in a zone that Function Compute supports. For more information, see Zones that Function Compute supports. If your database instance is not in a supported zone, you can create a vSwitch in the same zone as your function and specify its ID in the function's VPC configuration. Because vSwitches in the same VPC can communicate with each other over the private network, your function can use this vSwitch to access resources in other zones of the VPC. For more information, see What do I do if I receive the 'vSwitch is in unsupported zone' error?.
-
Log on to the Function Compute console and create a Python web function. On the function details page, select the Configuration tab, and then click Modify in the Advanced Settings section. In the Advanced Settings panel, find the Network section, enable VPC access for the function, and configure the destination VPC resources.
NoteMake sure that the VPC configured for the function is the same as the VPC to which the database instance is bound.
You can configure the VPC, vSwitch, and security group. We recommend that you deploy vSwitches in two or more zones to take full advantage of the multi-zone disaster recovery capabilities of Function Compute, which enhances the high availability of your service. The supported zones in the current region are cn-hangzhou-h, i, j, k, f, g, and b.
-
On the function details page, go to the Configuration tab. In the Network section, obtain the CIDR block of the vSwitch configured for the function.
-
Add the vSwitch CIDR block that you obtained in the previous step to the database access whitelist.
ImportantWe recommend that you authorize function access by using an IP address whitelist instead of a security group. Using a security group may cause intermittent connection failures, which can affect your service.
-
Go to the RDS instance list, select a region, and then click the target instance ID.
-
In the navigation pane on the left, click Whitelist and SecGroup.
On the Whitelist Settings page, you can view the current IP whitelist mode.
NoteOlder instances may operate in high-security mode. All new instances use the standard whitelist mode.
-
To the right of the default group, click Modify. In the Edit Whitelist dialog box, add the IPv4 CIDR block of the vSwitch that you obtained in step 2 to the whitelist, and then click OK.
After the configuration is complete, the function can access the RDS database through its internal endpoint.
-
Scenario 2: Across VPCs or regions
VPCs and regions are logically isolated. By default, you cannot access a database across VPCs or regions. To enable this, configure a static public IP address for your function. The system creates a public NAT gateway in the function's VPC, which allows the function to access the database over the internet by using the public IP address.
-
Log on to the Function Compute console. In the navigation pane on the left, click Functions. Select a region, and then create a function as prompted.
-
On the function details page, click the Configuration tab. In the Advanced Settings section, click Modify. In the Advanced Settings panel, find the Network section. To activate the static public IP, enable Static Public IP Address and disable Allow Default NIC to Access Internet. Then, click Deploy.
-
On the function details page, go to the Configuration tab. In the Network section, obtain the Elastic IP Address configured for the function.
-
Add the Elastic IP Address that you obtained in the previous step to the database access whitelist.
ImportantWe recommend that you authorize function access by using an IP address whitelist instead of a security group. Using a security group may cause intermittent connection failures, which can affect your service.
-
Go to the RDS instance list, select a region, and then click the target instance ID.
-
In the navigation pane on the left, click Whitelist and SecGroup.
On the Whitelist Settings page, you can view the current IP whitelist mode.
NoteOlder instances may operate in high-security mode. All new instances use the standard whitelist mode.
-
To the right of the default group, click Modify. In the Edit Whitelist dialog box, add the static public IP address that you obtained in step 3 to the whitelist, and then click OK.
A whitelist can contain specific IP addresses, such as
192.168.0.1, and CIDR blocks, such as192.168.0.0/24. Separate multiple entries with commas. Note: Setting the whitelist to0.0.0.0/0allows access from the public internet, while setting it to127.0.0.1blocks all external access. The new whitelist takes effect in about one minute.
After the configuration is complete, the function can access the RDS database through its public endpoint.
-
Step 2: Access RDS from your function
-
Log on to the Function Compute console. In the function list, find the target function. On its details page, click the Code tab and enter the following sample code in the editor.
from flask import Flask, jsonify import pymysql import os from datetime import datetime import logging app = Flask(__name__) # Global variable to store the singleton MySQL connection _mysql_connection = None # Create a database connection (singleton pattern) def getConnection(): global _mysql_connection try: # If the connection exists and is active, return it. if _mysql_connection is not None: try: # Test if the connection is valid with a simple query. with _mysql_connection.cursor() as cursor: cursor.execute("SELECT 1") # A simple query to test the connection status result = cursor.fetchone() if result and result[0] == 1: return _mysql_connection except pymysql.OperationalError: # If the connection is broken, reset it. _mysql_connection = None # If the connection does not exist or is broken, create a new one. _mysql_connection = pymysql.connect( host=os.environ['MYSQL_HOST'], port=int(os.environ['MYSQL_PORT']), user=os.environ['MYSQL_USER'], password=os.environ['MYSQL_PASSWORD'], db=os.environ['MYSQL_DBNAME'] ) return _mysql_connection except Exception as e: logging.error(f"Error occurred during database connection: {e}") raise @app.route('/', defaults={'path': ''}) @app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE']) def hello_world(path): conn = getConnection() try: with conn.cursor() as cursor: # Query all records from the users table. You must change 'users' to your actual table name. sql = "SELECT * FROM users" cursor.execute(sql) result = cursor.fetchall() columns = [desc[0] for desc in cursor.description] # Get the list of column names # Convert the query result to a list of dictionaries users = [] for row in result: user = {} for idx, column_name in enumerate(columns): value = row[idx] if isinstance(value, datetime): # Handle datetime fields user[column_name] = value.strftime('%Y-%m-%d %H:%M:%S') else: user[column_name] = value users.append(user) if users: # Return the JSON response with all users return jsonify(users), 200 else: # If no users are found, return a 404 error return jsonify({'error': 'No users found'}), 404 except Exception as e: logging.error(f"Error occurred during database operation: {e}") return jsonify({'error': 'Database error'}), 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=9000) -
On the Function Details page, select the Configuration tab, find Advanced Settings, and click Modify on its right. In the Advanced Settings panel, find the Environment Variables section, configure the following environment variables, and then click Deploy.
Parameter
Value
Description
MYSQL_HOST
rm-bp19u8e76ae****.mysql.rds.aliyuncs.com
The endpoint of the RDS instance.
-
If you are accessing an RDS database in the same VPC, set this environment variable to the internal endpoint of the database.
-
If you are accessing an RDS database across different VPCs or regions, set this environment variable to the public endpoint of the database.
In the RDS instance list, click the ID of the target RDS instance. In the navigation pane on the left, click Database Connection. On the Database Connection page, you can obtain the internal or public endpoint of the database.
MYSQL_DBNAME
db_test
The name of the database created in the RDS instance.
MYSQL_PASSWORD
*****
The database password.
MYSQL_PORT
3306
The private port of the database instance.
MYSQL_USER
dms_user_****
The name of the account created in the RDS instance.
-
-
On the function details page, click the Code tab, and then click Test Function. After the function executes successfully, check the returned result to confirm that the query completed.
The returned JSON data contains user records with fields such as
id,username,email,password_hash,created_at, andupdated_at.
More information
-
For more examples of accessing an ApsaraDB RDS for MySQL database, see Function Compute Python accessing MySQL database.
-
If you cannot access your database, troubleshoot the issue based on its symptoms. For more information, see Common causes of database access failures.
-
ApsaraDB RDS supports the MySQL, SQL Server, PostgreSQL, and MariaDB database engines. For more information, see Introduction to ApsaraDB RDS.
-
To use the Serverless Devs command-line tool to create a function and access an ApsaraDB RDS for MySQL database, follow these steps.