Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用sqlalchemy安全地进行并发更新?_Python_Sqlalchemy - Fatal编程技术网

Python 如何使用sqlalchemy安全地进行并发更新?

Python 如何使用sqlalchemy安全地进行并发更新?,python,sqlalchemy,Python,Sqlalchemy,我这里有一个玩具程序,它是用来混淆更新并添加到内存数据库中的。我的目的是将不同的项添加到数据库中,然后在单独的线程中更新每个项上的两个非主字段 然而,当在这个玩具程序中打印结果时,只有一个字段在要写入的第二个线程的末尾被更新。我的理解是 session.query(User).populate_existing().with_for_update( read=False, nowait=False, of=User).fil

我这里有一个玩具程序,它是用来混淆更新并添加到内存数据库中的。我的目的是将不同的项添加到数据库中,然后在单独的线程中更新每个项上的两个非主字段

然而,当在这个玩具程序中打印结果时,只有一个字段在要写入的第二个线程的末尾被更新。我的理解是

session.query(User).populate_existing().with_for_update(
            read=False,
            nowait=False,
            of=User).filter_by(name=u.name).one()
应该从数据库中重新提取该项,然后在修改该项之前锁定该项的行。因此,更新项目的第二个线程应该将
全名
昵称
都设置为新的(尽管很愚蠢)值

我在这里做错了什么,而这从来没有发生过

程序代码:

import random, time
import multiprocessing
from sqlalchemy import create_engine, Column, Integer, String, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()


class User(Base):
    __tablename__ = 'users'
    __table_args__ = (UniqueConstraint('nickname', 'fullname'),)
    name = Column(String, primary_key=True)
    fullname = Column(String)
    nickname = Column(String)

    def __repr__(self):
        return "<User(name='%s', fullname='%s', nickname='%s')>" % (
            self.name, self.fullname, self.nickname)


engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)


def database_change(count, id, out_list, engine):
    """
    Creates an empty list and then appends a
    random number to the list 'count' number
    of times. A CPU-heavy operation!
    """
    Session = sessionmaker(bind=engine)
    session = Session()

    name = ['CHEW', 'MARS BAR'][id]
    for i in range(size):
        time.sleep(random.random())
        user = User(
            name=f'cowface{i}',
            fullname=f"biscuit{i}",
            nickname=f'blah{i}')
        print(i)
        session.add(user)
        print(f'thread {id}, number {i}')
    session.commit()
    for u in session.query(User).all():

        print(u)
        new_u = session.query(User).populate_existing().with_for_update(
            read=False,
            nowait=False,
            of=User).filter_by(name=u.name).one()

        print(f'thread {id} modifying')
        if id == 0:
            new_u.fullname = name
        if id == 1:
            new_u.nickname = name
        session.commit()
    print(session.query(User).all())
    session.close()


if __name__ == "__main__":

    size = 10   # Number of random items to add
    procs = 2   # Number of processes to create

    # Create a list of jobs and then iterate through
    # the number of processes appending each process to
    # the job list
    jobs = []
    for i in range(0, procs):
        out_list = list()
        process = multiprocessing.Process(target=database_change,
                                          args=(size, i, out_list, engine))
        jobs.append(process)

    # Start the processes (i.e. calculate the random number lists)
    for j in jobs:
        j.start()

    # Ensure all of the processes have finished
    for j in jobs:
        j.join()
    print("operation complete.")
import random,time
导入多处理
从sqlalchemy导入创建引擎、列、整数、字符串、唯一约束
从sqlalchemy.ext.declarative导入声明性基础
从sqlalchemy.orm导入sessionmaker
Base=声明性_Base()
类用户(基本):
__tablename_uu='users'
__表参数(UniqueConstraint('昵称','fullname'),)
名称=列(字符串,主键=True)
fullname=列(字符串)
昵称=列(字符串)
定义报告(自我):
返回“”%(
self.name、self.fullname、self.昵称)
engine=create_engine('sqlite://:memory:',echo=True)
Base.metadata.create_all(引擎)
def数据库更改(计数、id、输出列表、引擎):
"""
创建一个空列表,然后附加一个
随机数到列表“计数”数
好几次。一个CPU繁重的操作!
"""
会话=会话生成器(绑定=引擎)
会话=会话()
name=['CHEW','MARS BAR'][id]
对于范围内的i(尺寸):
time.sleep(random.random())
用户=用户(
name=f'cowface{i}',
全名=f“饼干{i}”,
昵称=f'blah{i}')
印刷品(一)
session.add(用户)
打印(f'thread{id},number{i})
session.commit()
对于会话中的u.query(用户).all():
打印(u)
new\u=session.query(用户)。使用用于更新的\u填充\u existing()(
read=False,
nowait=False,
of=User).filter_by(name=u.name).one()
打印(f'thread{id}修改')
如果id==0:
new_.fullname=名称
如果id==1:
新昵称=名称
session.commit()
打印(session.query(User.all())
session.close()
如果名称=“\uuuuu main\uuuuuuuu”:
大小=10#要添加的随机项目数
procs=2#要创建的进程数
#创建作业列表,然后遍历
#将每个进程附加到的进程数
#工作清单
工作=[]
对于范围内的i(0,进程):
out_list=list()
进程=多进程。进程(目标=数据库更改,
args=(大小、i、输出列表、引擎))
jobs.append(进程)
#启动流程(即计算随机数列表)
对于工作中的j:
j、 开始()
#确保所有流程都已完成
对于工作中的j:
j、 加入
打印(“操作完成”)