Python 烧瓶中的原子插入

Python 烧瓶中的原子插入,python,flask,sqlalchemy,flask-sqlalchemy,Python,Flask,Sqlalchemy,Flask Sqlalchemy,在Flask和SQLAlchemy中实现以下功能有一个问题:我有一种用Flask编写的博客应用程序,用户可以在其中编写文本块。所以我有一个用户模型和一个文本块模型,文本块需要是唯一的。文本块可以从两个不同的客户端应用程序写入和发送,并且可以同时打开。我需要使时间块的插入和处理成为原子的,这样两个客户端应用程序就不会同时插入和处理同一个时间块。 模型: class TextblockModel(db.Model): __tablename__ = "textblock"

在Flask和SQLAlchemy中实现以下功能有一个问题:我有一种用Flask编写的博客应用程序,用户可以在其中编写文本块。所以我有一个用户模型和一个文本块模型,文本块需要是唯一的。文本块可以从两个不同的客户端应用程序写入和发送,并且可以同时打开。我需要使时间块的插入和处理成为原子的,这样两个客户端应用程序就不会同时插入和处理同一个时间块。 模型:

class TextblockModel(db.Model):
    __tablename__ = "textblock"

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    text = db.Column(db.Text, default="", nullable=False)

    user = db.relationship("User", backref=db.backref("texts", lazy=True))

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    password = db.Column(db.String(255))
对于两个客户端应用程序中的每一个,我都有一个post端点:

def post1(self):
        blocks = insert_block_into_db(request.json, current_user, CLIENTAPP1)
        process_blocks(blocks)

def post2(self):
        blocks = insert_block_into_db(request.json, current_user, CLIENTAPP2)
        process_blocks(blocks)
我需要使文本块的插入和处理原子化。比如说:

def post1(self):
    with lock:
        blocks = insert_block_into_db(request.json, current_user, WEBAPP1)
        process_blocks(blocks)

def post2(self):
    with lock:
        blocks = insert_block_into_db(request.json, current_user, WEBAPP2)
        process_blocks(blocks)

但我认为普通的Python锁不起作用,因为WSGI会产生多个进程来处理请求。此外,我不需要锁定所有内容,只需要锁定与当前用户相关的行。有人知道我如何解决这个问题吗?

如果您使用的是gunicorn,那么您可以在
gunicorn.conf
中设置
preload\u app=True
。这确保了锁在工作人员之间共享(即进程)


一个更不依赖Web服务器的解决方案是使用。这是一个创建操作系统全局锁的很棒的包。因此,可以跨进程共享锁。锁定会在指定目录中创建一个用作共享资源的空文件夹。由于根据POSIX标准,创建和删除目录是一个原子操作,因此该机制允许跨进程锁定。我不确定它是否在非UNIX机器上工作,例如Windows。

您需要对使块唯一的列设置唯一索引/约束。是的,我知道,但我需要将块插入到块数据库中,并将块处理为关键部分。一次只能有一个线程为用户执行该操作。