sqlalchemy-多線程、多並發下修改數據庫數據


sqlalchemy中多線程下,讀取數據庫信息同時修改數據庫信息可能會出現幻讀。

創建數據庫

from flask_sqlalchemy import SQLAlchemy
from flask import Flask

app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:root@localhost:3306/test"  # 數據庫要先創建
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SECRET_KEY"] = "DsdfFHERsdadad234+J"

db = SQLAlchemy(app)


class Stu(db.Model):
    __tablename__ = "student"  # 自動生成表,表名為student
    id = db.Column(db.Integer, primary_key=True)  # 創建一個整數型的主鍵
    name = db.Column(db.String(20), nullable=False)
    select_num = db.Column(db.Integer, nullable=False)
if __name__ == '__main__':
    db.create_all()

 創建一個案例

from model import Stu,db

stu = Stu()
stu.name = "張三"
stu.select_num = 0
db.session.add(stu)
db.session.commit()
from model import Stu, db
from threading import Thread


def add_execute_times():
    student = Stu.query.filter(Stu.id == 1).one()
    student.select_num += 1
    print(student.select_num)
    stu = Stu.query.filter(Stu.id == 1).update({"select_num": student.select_num})
    db.session.commit()


thread_list = []
for i in range(10):
    t = Thread(target=add_execute_times)
    thread_list.append(t)
for i in thread_list:
    i.start()
for i in thread_list:
    i.join()
輸出結果:

1
11

 
         

1
1
1
11
1

 
         

2

 

為了保證讀取數據的原子性,可以采用鎖來控制數據庫的讀取。

在sqlalchemy中,with_for_update(self, read=False, nowait=False, of=None)語句可以為數據庫添加鎖。

  • read:是標識加互斥鎖還是共享鎖. 當為 True 時, 即 for share 的語句, 是共享鎖. 多個事務可以獲取共享鎖, 互斥鎖只能一個事務獲取. 有"多個地方"都希望是"這段時間我獲取的數據不能被修改, 我也不會改", 那么只能使用共享鎖.
  • nowait:其它事務碰到鎖, 是否不等待直接"報錯".
  • of:指明上鎖的表, 如果不指明, 則查詢中涉及的所有表(行)都會加鎖.
from model import Stu, db
from threading import Thread


def add_execute_times():
student = Stu.query.with_for_update(read=False, nowait=False).filter(Stu.id == 1).one()
  #添加鎖with_for_update,鎖會在commit時打開
student.select_num += 1
print(student.select_num)
stu = Stu.query.filter(Stu.id == 1).update({"select_num": student.select_num})
db.session.commit()


thread_list = []
for i in range(10):
t = Thread(target=add_execute_times)
thread_list.append(t)
for i in thread_list:
i.start()
for i in thread_list:
i.join()
輸出結果:

1
2
3
4
5
6
7
8
9
10

 
          
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM