asyncpg.exceptions._base.InterfaceError:cannot perform operation: another op

文章讲述了在使用FastApi、asyncpg和psql数据库时,由于业务逻辑处理时间长,用户连续点击接口导致的错误。错误的根本原因是不同请求使用了同一个数据库连接。为了解决这个问题,文章提出了通过引入Redis实现锁机制,确保同一时刻只有一个请求在执行,从而避免了操作冲突。示例代码展示了如何创建Redis连接池以及如何使用锁装饰器来保护关键操作。

错误详细信息:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值