此示例演示如何使用 Azure SDK for Python 管理库以编程方式创建 Azure Database for MySQL 灵活服务器和相应的数据库。 它还包括一个基本脚本,该脚本使用 mysql-connector-python 库(不是 Azure SDK 的一部分)连接到数据库并查询数据库。
可以通过修改相关的 SDK 导入和 API 调用来调整此示例,以创建 Azure Database for PostgreSQL 灵活服务器。
如果想要使用 Azure CLI,本文稍后会提供 等效的 Azure CLI 命令 。 有关图形体验,请参阅 Azure 门户文档:
除非另有指定,否则所有示例和命令在 Linux/macOS bash 和 Windows 命令行界面中一致工作。
1:设置本地开发环境
如果尚未设置,请设置一个可在其中运行代码的环境。 下面是一些选项:
使用
venv
或所选工具配置 Python 虚拟环境。 若要开始使用虚拟环境,请务必激活它。 若要安装 python,请参阅 “安装 Python”。#!/bin/bash # Create a virtual environment python -m venv .venv # Activate the virtual environment source .venv/Scripts/activate # only required for Windows (Git Bash)
使用 conda 环境。 若要安装 Conda,请参阅 “安装 Miniconda”。
在 Visual Studio Code 或 GitHub Codespaces中使用 开发容器。
2:安装所需的 Azure 库包
在此步骤中,安装创建数据库所需的 Azure SDK 库。
在控制台中创建一个 requirements.txt 文件,其中列出了此示例中使用的管理库:
azure-mgmt-resource azure-mgmt-rdbms azure-identity mysql-connector-python
注释
该
mysql-connector-python
库不是 Azure SDK 的一部分。 它是第三方库,可用于连接到 MySQL 数据库。 还可以使用其他库(例如PyMySQL
或SQLAlchemy
)连接到 MySQL 数据库。在激活虚拟环境的控制台中,安装要求:
pip install -r requirements.txt
注释
在 Windows 上,尝试将 mysql 库安装到 32 位 Python 库中会生成 有关 mysql.h 文件的错误。 在这种情况下,请安装 64 位版本的 Python,然后重试。
3. 设置环境变量
在此步骤中,你将设置环境变量,以便在本文中的代码中使用。 代码使用 os.environ
方法来检索值。
#!/bin/bash
export AZURE_RESOURCE_GROUP_NAME=<ResourceGroupName> # Change to your preferred resource group name
export LOCATION=<Location> # Change to your preferred region
export AZURE_SUBSCRIPTION_ID=$(az account show --query id --output tsv)
export PUBLIC_IP_ADDRESS=$(curl -s https://api.ipify.org)
export DB_SERVER_NAME=<DB_Server_Name> # Change to your preferred DB server name
export DB_ADMIN_NAME=<DB_Admin_Name> # Change to your preferred admin name
export DB_ADMIN_PASSWORD=<DB_Admin_Passwrod> # Change to your preferred admin password
export DB_NAME=<DB_Name> # Change to your preferred database name
export DB_PORT=3306
export version=ServerVersion.EIGHT0_21
4:编写代码以使用数据库创建和配置 MySQL 灵活服务器
在此步骤中,你将使用以下代码创建名为 provision_blob.py 的 Python 文件。 此 Python 脚本使用 Azure SDK for Python 管理库创建资源组、MySQL 灵活服务器和该服务器上的数据库。
import random, os
from azure.identity import DefaultAzureCredential
from azure.mgmt.resource import ResourceManagementClient
from azure.mgmt.rdbms.mysql_flexibleservers import MySQLManagementClient
from azure.mgmt.rdbms.mysql_flexibleservers.models import Server, ServerVersion
# Acquire a credential object using CLI-based authentication.
credential = DefaultAzureCredential()
# Retrieve subscription ID from environment variable
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
# Retrieve resource group name and ___location from environment variables
RESOURCE_GROUP_NAME = os.environ["AZURE_RESOURCE_GROUP_NAME"]
LOCATION = os.environ["LOCATION"]
# Step 1: Provision the resource group.
resource_client = ResourceManagementClient(credential, subscription_id)
rg_result = resource_client.resource_groups.create_or_update(RESOURCE_GROUP_NAME,
{ "___location": LOCATION })
print(f"Provisioned resource group {rg_result.name}")
# For details on the previous code, see Example: Provision a resource group
# at https://docs.microsoft.com/azure/developer/python/azure-sdk-example-resource-group
# Step 2: Provision the database server
# Retrieve server name, admin name, and admin password from environment variables
db_server_name = os.environ.get("DB_SERVER_NAME")
db_admin_name = os.environ.get("DB_ADMIN_NAME")
db_admin_password = os.environ.get("DB_ADMIN_PASSWORD")
# Obtain the management client object
mysql_client = MySQLManagementClient(credential, subscription_id)
# Provision the server and wait for the result
server_version = os.environ.get("DB_SERVER_VERSION")
poller = mysql_client.servers.begin_create(RESOURCE_GROUP_NAME,
db_server_name,
Server(
___location=LOCATION,
administrator_login=db_admin_name,
administrator_login_password=db_admin_password,
version=ServerVersion[server_version] # Note: dictionary-style enum access
)
)
server = poller.result()
print(f"Provisioned MySQL server {server.name}")
# Step 3: Provision a firewall rule to allow the local workstation to connect
RULE_NAME = "allow_ip"
ip_address = os.environ["PUBLIC_IP_ADDRESS"]
# Provision the rule and wait for completion
poller = mysql_client.firewall_rules.begin_create_or_update(RESOURCE_GROUP_NAME,
db_server_name, RULE_NAME,
{ "start_ip_address": ip_address, "end_ip_address": ip_address }
)
firewall_rule = poller.result()
print(f"Provisioned firewall rule {firewall_rule.name}")
# Step 4: Provision a database on the server
db_name = os.environ.get("DB_NAME", "example-db1")
poller = mysql_client.databases.begin_create_or_update(RESOURCE_GROUP_NAME,
db_server_name, db_name, {})
db_result = poller.result()
print(f"Provisioned MySQL database {db_result.name} with ID {db_result.id}")
代码中的身份验证
本文稍后会使用 Azure CLI 登录到 Azure,以执行示例代码。 如果帐户有足够的权限在 Azure 订阅中创建资源组和存储资源,则脚本应成功运行,而无需其他配置。
若要在生产环境中使用,建议通过设置相应的环境变量来向服务主体进行身份验证。 此方法可实现适用于自动化的安全非交互式访问。 有关设置说明,请参阅 如何使用 Azure 服务对 Python 应用进行身份验证。
确保为服务主体分配了具有足够权限的角色,例如订阅或资源组级别的参与者角色。 有关分配角色的详细信息,请参阅 Azure 中的基于角色的访问控制(RBAC)。
代码中使用的类的参考链接
- ResourceManagementClient (azure.mgmt.resource)
- MySQLManagementClient (azure.mgmt.rdbms.mysql_flexibleservers)
- 服务器(azure.mgmt.rdbms.mysql_flexibleservers.models)
- ServerVersion (azure.mgmt.rdbms.mysql_flexibleservers.models)
有关 PostreSQL 数据库服务器,请参阅:
5:运行脚本
如果尚未登录,请使用 Azure CLI 登录到 Azure:
az login
运行以下脚本:
python provision_db.py
脚本需要一两分钟才能完成。
6:插入记录并查询数据库
在此步骤中,将在数据库中创建表并插入记录。 可以使用 mysql-connector 库连接到数据库并运行 SQL 命令。
使用以下代码创建名为 use_db.py 的文件。
此代码仅适用于 MySQL;为 PostgreSQL 使用不同的库。
import os import mysql.connector db_server_name = os.environ["DB_SERVER_NAME"] db_admin_name = os.getenv("DB_ADMIN_NAME") db_admin_password = os.getenv("DB_ADMIN_PASSWORD") db_name = os.getenv("DB_NAME") db_port = os.getenv("DB_PORT") connection = mysql.connector.connect(user=db_admin_name, password=db_admin_password, host=f"{db_server_name}.mysql.database.azure.com", port=db_port, database=db_name, ssl_ca='./BaltimoreCyberTrustRoot.crt.pem') cursor = connection.cursor() """ # Alternate pyodbc connection; include pyodbc in requirements.txt import pyodbc driver = "{MySQL ODBC 5.3 UNICODE Driver}" connect_string = f"DRIVER={driver};PORT=3306;SERVER={db_server_name}.mysql.database.azure.com;" \ f"DATABASE={DB_NAME};UID={db_admin_name};PWD={db_admin_password}" connection = pyodbc.connect(connect_string) """ table_name = "ExampleTable1" sql_create = f"CREATE TABLE {table_name} (name varchar(255), code int)" cursor.execute(sql_create) print(f"Successfully created table {table_name}") sql_insert = f"INSERT INTO {table_name} (name, code) VALUES ('Azure', 1)" insert_data = "('Azure', 1)" cursor.execute(sql_insert) print("Successfully inserted data into table") sql_select_values= f"SELECT * FROM {table_name}" cursor.execute(sql_select_values) row = cursor.fetchone() while row: print(str(row[0]) + " " + str(row[1])) row = cursor.fetchone() connection.commit()
所有这些代码都使用 mysql.connector API。 唯一特定于 Azure 的部分是 MySQL 服务器的完整主机域(mysql.database.azure.com)。
接下来,下载通过 TSL/SSL 与 Azure Database for MySQL 服务器通信所需的证书。 有关详细信息,请参阅 Azure Database for MySQL 文档中 的“获取 SSL 证书 ”。
#!/bin/bash # Download Baltimore CyberTrust Root certificate required for Azure MySQL SSL connections CERT_URL="https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem" CERT_FILE="BaltimoreCyberTrustRoot.crt.pem" echo "Downloading SSL certificate..." curl -o "$CERT_FILE" "$CERT_URL"
最后,运行代码:
python use_db.py
如果看到客户端 IP 地址不允许的错误,请检查是否正确定义了环境变量 PUBLIC_IP_ADDRESS
。 如果已使用错误的 IP 地址创建了 MySQL 服务器,则可以在 Azure 门户中添加另一个服务器。 在门户中,选择 MySQL 服务器,然后选择 “连接安全性”。 将工作站的 IP 地址添加到允许的 IP 地址列表中。
7:清理资源
如果不需要保留在此示例中创建的资源组和存储资源,请运行 az group delete 命令。
资源组不会在订阅中产生任何持续费用,但资源组中的资源(如存储帐户)可能会继续产生费用。 清理不经常使用的组是一种很好的做法。
--no-wait
参数允许命令立即返回,而不是等待作完成。
#!/bin/bash
az group delete -n $AZURE_RESOURCE_GROUP_NAME --no-wait
还可以使用 ResourceManagementClient.resource_groups.begin_delete
方法从代码中删除资源组。 示例中的代码 :创建资源组 演示用法。
有关参考:等效的 Azure CLI 命令
以下 Azure CLI 命令完成与 Python 脚本相同的预配步骤。 对于 PostgreSQL 数据库,请使用 az postgres flexible-server
命令。
#!/bin/bash
#!/bin/bash
# Set variables
export LOCATION=<Location> # Change to your preferred region
export AZURE_RESOURCE_GROUP_NAME=<ResourceGroupName> # Change to your preferred resource group name
export DB_SERVER_NAME=<DB_Server_Name> # Change to your preferred DB server name
export DB_ADMIN_NAME=<DB_Admin_Name> # Change to your preferred admin name
export DB_ADMIN_PASSWORD=<DB_Admin_Password> # Change to your preferred admin password
export DB_NAME=<DB_Name> # Change to your preferred database name
export DB_SERVER_VERSION="5.7"
# Get public IP address
export PUBLIC_IP_ADDRESS=$(curl -s https://api.ipify.org)
# Provision the resource group
echo "Creating resource group: $AZURE_RESOURCE_GROUP_NAME"
az group create \
--___location "$LOCATION" \
--name "$AZURE_RESOURCE_GROUP_NAME"
# Provision the MySQL Flexible Server
echo "Creating MySQL Flexible Server: $DB_SERVER_NAME"
az mysql flexible-server create \
--___location "$LOCATION" \
--resource-group "$AZURE_RESOURCE_GROUP_NAME" \
--name "$DB_SERVER_NAME" \
--admin-user "$DB_ADMIN_NAME" \
--admin-password "$DB_ADMIN_PASSWORD" \
--sku-name Standard_B1ms \
--version "$DB_SERVER_VERSION" \
--yes
# Provision a firewall rule to allow access from the public IP address
echo "Creating firewall rule for public IP: $PUBLIC_IP_ADDRESS"
az mysql flexible-server firewall-rule create \
--resource-group "$AZURE_RESOURCE_GROUP_NAME" \
--name "$DB_SERVER_NAME" \
--rule-name allow_ip \
--start-ip-address "$PUBLIC_IP_ADDRESS" \
--end-ip-address "$PUBLIC_IP_ADDRESS"
# Provision the database
echo "Creating database: $DB_NAME"
az mysql flexible-server db create \
--resource-group "$AZURE_RESOURCE_GROUP_NAME" \
--server-name "$DB_SERVER_NAME" \
--database-name "$DB_NAME"
echo "MySQL Flexible Server and database created successfully."