错误详细信息:
asyncpg.exceptions._base.InterfaceError: cannot perform operation: another operation is in progress
出现错误的场景:
FastApi + asyncpg + psql数据库,因为某个业务逻辑处理时间较长,连续点击两次接口就会出现这样的错误。
出现错误的原因:
不同的请求使用同一个数据库链接
解决办法:
加锁保证同一时刻只有一个请求在进行
class RedisConnectionPool(object):
_CONFIG_NAME = 'REDIS_CONFIG'
def __init__(self):
self.conn = None
self._loop = None
self.pool: Optional[Redis] = None
self.app = None
async def init_app(self, app) -> Redis:
self.app = app
config = app.config[self._CONFIG_NAME]
self._loop = app.loop
host = config["host"]
port = config["port"]
password = config['password']
self.pool = await aioredis.create_redis_pool(
f'redis://{host}:{port}',
password=password,
loop=self._loop
)
return self.pool
def lock(self, key, timeout=30, wait_timeout=30):
def decorator(f):
@functools.wraps(f)
async def decorated_function(*args, **kwargs):
async with RedisLock(self.pool, key=key, timeout=timeout, wait_timeout=wait_timeout) as lock:
return await f(*args, **kwargs)
return decorated_function
return decorator
使用锁:
redis = RedisConnectionPool()
@redis.lock("my_lock_name")
async def test():
pass
文章讲述了在使用FastApi、asyncpg和psql数据库时,由于业务逻辑处理时间长,用户连续点击接口导致的错误。错误的根本原因是不同请求使用了同一个数据库连接。为了解决这个问题,文章提出了通过引入Redis实现锁机制,确保同一时刻只有一个请求在执行,从而避免了操作冲突。示例代码展示了如何创建Redis连接池以及如何使用锁装饰器来保护关键操作。

被折叠的 条评论
为什么被折叠?



