我有一個如何在我的博客http://techspot.zzzeek.org/2012/01/11/django-style-database-routers-in-sqlalchemy/上執行此操作的示例。基本上,您可以增強會話,以便在逐個查詢的基礎上從主服務器或從服務器中進行選擇。這種方法的一個潛在的小故障是,如果你有一個事務需要6個查詢,你最終可能會在一個請求中使用兩個從屬服務器......但我們只是試圖模仿Django的功能:)
A稍顯不足魔術的辦法,也規定的使用更加明確我用過的範圍上觀點可調用一個裝飾(無論他們是所謂的燒瓶),像這樣:
@with_slave
def my_view(...):
# ...
with_slave會做這樣的事情,假設你有一個Session和一些引擎設置:
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)
調用註冊表來獲取當前線程的實際Session對象,如果它不存在則創建它 - 但是由於我們傳遞了一個參數,scoped_session將斷言我們的Session這裏絕對是全新的。
您將它指向所有後續SQL的「從屬」。然後,當請求結束時,您可以確保Flask應用程序調用Session.remove()
來清除該線程的註冊表。當註冊表接下來在同一個線程中使用時,它將成爲綁定回「主」的新會話。
或變體,你要使用的「奴隸」只爲這一號召,這是因爲它恢復任何現有的綁定回會話「更安全」:
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有某種「請求開始」事件,那麼你可以在那時設置它。
日Thnx zzzeek這有很大幫助。在sqlalchemy上所有令人敬畏的工作的榮譽。 –
Rad評論,偉大的代碼示例呢!如果sqlalchemy有一些方法可以自動執行查詢分析和路由,那將是非常好的,但在一個查詢可能導致tmp表或其他寫入操作的世界中,由於可能通常只會讀取,而這需要諸如請求在提交查詢之前,來自後端的查詢計劃將比在大多數情況下值得的更麻煩。 –
我們有「查詢分析」選項,但它需要您自己編寫分析。水平分片系統說明了這種技術的一個例子,參見http://docs.sqlalchemy.org/en/rel_0_7/orm/extensions/horizontal_shard.html。 – zzzeek