首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读从站、读写主站设置

读从站、读写主站设置
EN

Stack Overflow用户
提问于 2012-01-21 05:13:02
回答 2查看 13K关注 0票数 27

我有一个Flask,mysql,它使用一个SQLAlchemy服务器。我想扩展数据库设置,使之具有一个只读的从服务器,这样我就可以在继续写入主数据库服务器的同时,在主服务器和从服务器之间分配读操作。

我已经看过几个选项,我相信我不能用普通的SQLAlchemy做到这一点。取而代之的是,我计划在我的webapp中创建2个数据库句柄,分别用于主数据库服务器和从数据库服务器。然后使用一个简单的随机值,使用主/从db句柄进行"SELECT“操作。

然而,我不确定这是否是使用SQLAlchemy的正确方式。关于如何做到这一点有什么建议/小贴士吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-24 09:36:22

我在http://techspot.zzzeek.org/2012/01/11/django-style-database-routers-in-sqlalchemy/的博客上有一个如何做到这一点的例子。基本上,您可以增强会话,使其在逐个查询的基础上从主或从中进行选择。这种方法的一个潜在问题是,如果您有一个调用六个查询的事务,您可能最终会在一个request....but中同时使用两个从机,我们只是试图模仿Django的功能:)

还有一种不太神奇的方法,它也更明确地确定了我使用的使用范围,那就是在视图可调用(在Flask中称为它们)上使用一个装饰器,如下所示:

代码语言:javascript
复制
@with_slave
def my_view(...):
   # ...

假设你有一个会话并设置了一些引擎,with_slave会这样做:

代码语言:javascript
复制
master = create_engine("some DB")
slave = create_engine("some other DB")
Session = scoped_session(sessionmaker(bind=master))

def with_slave(fn):
    def go(*arg, **kw):
        s = Session(bind=slave)
        return fn(*arg, **kw)
    return go

这个想法是调用Session(bind=slave)来调用注册表来获取当前线程的实际会话对象,如果它不存在就创建它-然而,由于我们传递了一个参数,scoped_session将断言我们在这里创建的会话绝对是全新的。

对于所有后续的SQL,您将其指向“从”。然后,当请求结束时,您将确保Flask应用程序正在调用Session.remove()来清除该线程的注册表。当注册表下一次在同一线程上使用时,它将是一个绑定回"master“的新会话。

或者是一个变种,你只想对那个调用使用"slave“,这是”安全的“,因为它会将任何现有的绑定恢复回会话:

代码语言:javascript
复制
def with_slave(fn):
    def go(*arg, **kw):
        s = Session()
        oldbind = s.bind
        s.bind = slave
        try:
            return fn(*arg, **kw)
        finally:
            s.bind = oldbind
    return go

对于这些装饰器中的每一个,你都可以颠倒过来,让会话绑定到一个“从”上,在这个“从”上,装饰器把它放在“主”上进行写操作。在这种情况下,如果你想要一个随机的从属,如果Flask有某种“请求开始”事件,你可以在那个时候设置它。

票数 41
EN

Stack Overflow用户

发布于 2016-05-12 11:49:22

或者,我们可以尝试另一种方法。例如,我们可以声明两个不同的类,所有的实例属性都是相同的,但是__bind__类属性是不同的。因此,我们可以使用rw类进行读写,使用r类进行只读。:)

我认为这种方式更容易、更可靠。:)

我们声明两个db模型,因为我们可以在两个不同的db中拥有具有相同名称的表。这样,当两个模型具有相同的__tablename__.时,我们也可以绕过'extend_existing‘错误

下面是一个示例:

代码语言:javascript
复制
app = Flask(__name__)
app.config['SQLALCHEMY_BINDS'] = {'rw': 'rw', 'r': 'r'}
db = SQLAlchemy(app)
db.Model_RW = db.make_declarative_base()

class A(db.Model):
    __tablename__ = 'common'
    __bind_key__ = 'r'

class A(db.Model_RW):
    __tablename__ = 'common'
    __bind_key__ = 'rw'    
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8947918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档