AWS Lambda复用MySQL连接导致数据查询缺失问题咨询
AWS Lambda + API Gateway 数据库查询数据缺失问题
问题场景
使用AWS Lambda搭配API Gateway时遇到如下问题:
- 一个Lambda负责向MySQL数据库插入数据,另一个Lambda负责查询数据列表
- 初次查询时,新插入的数据会缺失;但再次调用查询Lambda时,所有数据均能正常获取
- 原本按推荐将数据库连接定义在Lambda handler之外,后续改为每次调用handler时强制关闭连接(即每次调用新建连接),问题得以解决
复现代码(PyMySQL)
def sample_code(): # Create Connection 1 (//Lambda 1) conn_1 = get_connection() cursor_1 = get_cursor(conn_1) random_string = str(random.randint(1, 100)) cursor_1.execute(SQL_INSERT, ("John", random_string)) conn_1.commit() print(f"1. Inserted {('John', random_string)}") cursor_1.execute(SQL_GET) result = cursor_1.fetchall() print(f"1. All rows -> {result=}") # Create a new Connection/Cursor 2 (//Lambda 2) conn_2 = get_connection() cur_2 = get_cursor(conn_2) random_string = str(random.randint(1, 100)) cur_2.execute(SQL_INSERT, ("Doe", random_string)) conn_2.commit() print(f"2. Inserted {('Doe', random_string)}") cur_2.execute(SQL_GET) results = cur_2.fetchall() cur_2.close() conn_2.close() print(f"2. All rows -> {results=}") # Fetch results using Connection/Cursor 1. (Lambda 1) cursor_1.execute(SQL_GET) get_resp = cursor_1.fetchall() print(f"\n1. All rows {get_resp=}") # Create a new connection 3 (//Lambda 3) con3 = get_connection() cur_3 = get_cursor(con3) cur_3.execute(SQL_GET) results = cur_3.fetchall() print(f"\n3. All rows -> {results=}")
输出结果
1. Inserted ('John', '75') 1. All rows -> result=((None, '75', 'John'),) 2. Inserted ('Doe', '66') 2. All rows -> results=((None, '75', 'John'), (None, '66', 'Doe')) 1. All rows get_resp=((None, '75', 'John'),) 3. All rows -> results=((None, '75', 'John'), (None, '66', 'Doe'))
核心疑问
- 为何用连接2插入的数据,连接1无法查询到?
- 是否必须关闭数据库连接/游标?
问题原因与解答
1. 数据查询不到的根本原因
这是MySQL事务隔离级别与Lambda执行环境复用共同作用的结果:
- MySQL默认事务隔离级别为
REPEATABLE READ(可重复读),该级别下,事务开启后会创建一致性快照,后续查询仅返回快照建立时的数据状态,无法看到其他事务提交的新数据。 - Lambda的执行环境复用机制:将连接定义在handler之外时,Lambda的暖环境会保留该连接,对应事务长期处于未关闭状态(除非显式提交/回滚并关闭连接)。当连接2插入数据并提交后,连接1的事务仍在使用初始快照,因此查不到新数据。
你的示例代码也验证了这一点:连接1未关闭,后续查询始终使用初始快照;而连接2关闭后,新创建的连接3能获取最新数据,因为新连接会生成全新的一致性快照。
2. 是否必须关闭连接/游标?
并非绝对“必须”,但在Lambda环境下强烈建议每次调用后关闭连接与游标,原因如下:
- 避免事务快照复用导致的数据不一致问题,即你遇到的场景。
- Lambda执行环境的复用具有不确定性,长期保留的连接可能因数据库端超时机制被强制断开,导致后续调用出现连接错误。
- 数据库连接数有限,Lambda并发调用若均保留连接,可能耗尽数据库连接池,导致新请求无法建立连接。
若想优化连接复用,可尝试:
- 在handler内显式提交事务(即使无修改操作),刷新连接快照,让后续查询获取最新数据。
- 给连接设置合理超时时间,或每次调用前检查连接有效性,无效则重新建立。
但最稳妥的方式仍是每次调用Lambda后关闭连接与游标,规避环境复用带来的各类问题。
内容的提问来源于stack exchange,提问作者Gokul
相关产品推荐
相关产品推荐

