如何使用Python连接AWS RDS MySql数据库

8

我正在尝试使用 PyMySQL 库,通过一个 Python 程序连接到在 AWS 上创建的 MySql 数据库。

# !/usr/bin/env python
# -*- coding: utf-8 -*-
import pymysql

host = 'admin.cjp8hsqu4je0.us-east-2.rds.amazonaws.com'
user = 'admin'
password = '12345678'
database = 'admin'

connection = pymysql.connect(host, user, password, database)
with connection:
    cur = connection.cursor()
    cur.execute("SELECT VERSION()")
    version = cur.fetchone()
    print("Database version: {} ".format(version[0]))


当我运行上面的代码时,我会得到以下错误:
Traceback (most recent call last):
  File "C:\Users\SuperPC\AppData\Local\Programs\Python\Python38-32\lib\site-packages\pymysql\connections.py", line 581, in connect
    sock = socket.create_connection(
  File "C:\Users\SuperPC\AppData\Local\Programs\Python\Python38-32\lib\socket.py", line 808, in create_connection
    raise err
  File "C:\Users\SuperPC\AppData\Local\Programs\Python\Python38-32\lib\socket.py", line 796, in create_connection
    sock.connect(sa)
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "bot.py", line 10, in <module>
    connection = pymysql.connect(host, user, password, database)
  File "C:\Users\SuperPC\AppData\Local\Programs\Python\Python38-32\lib\site-packages\pymysql\__init__.py", line 94, in Connect
    return Connection(*args, **kwargs)
  File "C:\Users\SuperPC\AppData\Local\Programs\Python\Python38-32\lib\site-packages\pymysql\connections.py", line 325, in __init__
    self.connect()
  File "C:\Users\SuperPC\AppData\Local\Programs\Python\Python38-32\lib\site-packages\pymysql\connections.py", line 630, in connect
    raise exc
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'admin.cjp8hsqu4je0.us-east-2.rds.amazonaws.com' (timed out)")

我做错了什么?我传递给函数的参数是正确的。可能是MySql驱动程序出现问题吗?


你是否已将你的RDS设置为公开可用?另外,你能展示一下你的RDS所使用的安全组吗? - Marcin
"您是否将您的RDS设置为公开可用?" 可能没有,您能告诉我们如何做吗?"另外,您能显示一下RDS的安全组吗?" VPC安全组 默认值(sg-09ddd998b30aa17c8) (活跃中) - Keriger
SG上的入站规则是什么?另外,RDS是否公开可用还不清楚。这是RDS设置中的一个选项。 - Marcin
我将提供一张带截图的答案,因为无法在评论中粘贴。 - Marcin
3个回答

8
如果您想从AWS外部通过互联网访问您的RDS,则应将其设置为“公开可用”:

enter image description here

此外,它应该放置在一个公共子网中(例如默认 VPC),并在其安全组中打开入站规则(良好实践是仅限于选定的 IP 或 IP 范围,而不是使用 0.0.0.0/0):

enter image description here

希望这可以帮助到你。

我也遇到了同样的错误。我按照上面提到的所有步骤进行了操作,但是我不知道出了什么问题。你能否提供一个解决方案? - siva
我的需求是,我想连接到RDS Aurora-mysql数据库并创建一个表。 - siva
@siva,我认为最好新开一个问题来讨论你的问题。 - Marcin

4

终于我找到了最终解决方案:

如果您有一个已经与 RDS 实例正确连接的 EC2 实例,您可以在它们之间打开 SSH 隧道,并使用 pymysql(Python 库)。

以下是拯救者代码!(我添加了一些代码和注释,但您可以通过下面的链接获取原始代码) 链接到拯救者的 Github

首先,请安装这些库:

  • !pip install sshtunnel

  • !pip install PyMySQL

      # Import libraries
      from sshtunnel import SSHTunnelForwarder
      import pymysql
    
      # SSH (ec2_public_dns, ec2_user, pem_path, remote_bind_address=(rds_instance_access_point, port))
      with SSHTunnelForwarder(('ec2-52-202-194-76.public-ec2-instance.amazonaws.com'), ssh_username="ec2-user", ssh_pkey="~/ssh-tunnel-rds.pem", remote_bind_address=('private-rds-instance.ckfkidfytpr4.us-east-1.rds.amazonaws.com', 3306)) as tunnel:
          print("****SSH Tunnel Established****")
    
          db = pymysql.connect(
              host='127.0.0.1', user="rdsuser",password="rdspassword",
              port=tunnel.local_bind_port, database="dbName"
          )
          # Run sample query in the database to validate connection
          try:
              # Print all the databases
              with db.cursor() as cur:
                  # Print all the tables from the database
                  cur.execute('SHOW TABLES FROM dbName')
                  for r in cur:
                      print(r)
    
                  # Print all the data from the table
                  cur.execute('SELECT * FROM table_name')
                  for r in cur:
                      print(r)
          finally:
              db.close()
    
      print("YAYY!!")
    

非常感谢!这确实是最终的解决方案! - soniaseguz
谢谢!确实是最终的解决方案! - undefined

4

此请求超时,这表明由于防火墙规则,您无法连接。

如果您在 EC2 实例或容器上运行此操作,则:

  • 确保 RDS 实例已配置为允许使用其安全组,通过端口 3306 连接到实例/容器的子网范围内的入站访问。

如果您在外部运行此操作,则需要执行以下操作之一:

  • 通过 VPN 连接到您的 VPC,并更新 RDS 的安全组以将您的本地 CIDR 范围列入白名单
  • 如果您无法使用 VPN,则需要创建 RDS 以使其可以公开访问,并使用安全组将入站访问列入白名单,以允许您的公共 IP 地址进行访问。

如果您正在使用 Lambda,则应完成以下操作:

  • 将 Lambda 迁移到 VPC 中,将安全组附加到 Lambda 上以允许出站访问(默认情况下,它应该允许对所有内容进行出站访问)。 它应该位于私有子网中
  • 更新 RDS 数据库的安全组,以允许通过端口 3306 对 Lambda 子网或附加到 Lambda 的安全组进行入站访问。

有关在 VPC 中配置 Lambda 的更多信息,请参见此文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接