基于scoped_session实现线程安全

一、基于scoped_session实现线程安全

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session
from models import Users

engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/db_flask", max_overflow=0, pool_size=5)
Session = sessionmaker(bind=engine)

"""
# 线程安全,基于本地线程实现每个线程用同一个session
# 特殊的:scoped_session中有原来方法的Session中的一下方法:

public_methods = (
    '__contains__', '__iter__', 'add', 'add_all', 'begin', 'begin_nested',
    'close', 'commit', 'connection', 'delete', 'execute', 'expire',
    'expire_all', 'expunge', 'expunge_all', 'flush', 'get_bind',
    'is_modified', 'bulk_save_objects', 'bulk_insert_mappings',
    'bulk_update_mappings',
    'merge', 'query', 'refresh', 'rollback',
    'scalar'
)
"""
#scoped_session类并没有继承Session,但是却又它的所有方法
session = scoped_session(Session)
# ############# 执行ORM操作 #############
obj1 = Users(name="randy")
session.add(obj1)

# 提交事务
session.commit()
# 关闭session
session.close()

二、底层实现原理

2.1 scoped_session进入类

from sqlalchemy.orm import scoped_session
session = scoped_session(Session)

for meth in Session.public_methods:
    setattr(scoped_session, meth, instrument(meth))
    
public_methods = (
        "__contains__",
        "__iter__",
        "add",
        "add_all",
        "begin",
        "begin_nested",
        "close",
        "commit",
        "connection",
        "delete",
        "execute",
        "expire",
        "expire_all",
        "expunge",
        "expunge_all",
        "flush",
        "get_bind",
        "is_modified",
        "bulk_save_objects",
        "bulk_insert_mappings",
        "bulk_update_mappings",
        "merge",
        "query",
        "refresh",
        "rollback",
        "scalar",
    )
  1. 首先进入点击scoped_session进入scoped_session类查看如下内容

    for meth in Session.public_methods:
        setattr(scoped_session, meth, instrument(meth))
    

    1577885203996

    为scoped_sesion类设置属性

  2. public_methods中内容:

    这是在Session类中的内容

    public_methods = (
            "__contains__",
            "__iter__",
            "add",
            "add_all",
            "begin",
            "begin_nested",
            "close",
            "commit",
            "connection",
            "delete",
            "execute",
            "expire",
            "expire_all",
            "expunge",
            "expunge_all",
            "flush",
            "get_bind",
            "is_modified",
            "bulk_save_objects",
            "bulk_insert_mappings",
            "bulk_update_mappings",
            "merge",
            "query",
            "refresh",
            "rollback",
            "scalar",
        )
    
  3. setattr(scoped_session, meth, instrument(meth))这句中的instrument是一个闭包函数

    改闭包函数中实现了对数据库中具体操作

    1577885753015

  4. self.registry()中实现如下,为其实现了一个线程

    class scoped_session(object):
      
        session_factory = None 
    
        def __init__(self, session_factory, scopefunc=None):
          
            self.session_factory = session_factory
    
            if scopefunc:
                self.registry = ScopedRegistry(session_factory, scopefunc)
            else:
                self.registry = ThreadLocalRegistry(session_factory)
    
    

    线程内容如下,最终利用线程中的local()模块中实现线程的安全,也就是操作数据的安全:

    class ThreadLocalRegistry(ScopedRegistry):
    
    
        def __init__(self, createfunc):
            self.createfunc = createfunc
            self.registry = threading.local()
    

总结:

  • session = scoped_session(Session)这个session是那一个操作过来就是哪一个操作,只操作自己对数据的操作,从而保证了线程的安全
posted @ 2021-11-06 20:32  RandySun  阅读(323)  评论(0编辑  收藏  举报