當前位置:首頁 » 數據倉庫 » 資料庫session
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

資料庫session

發布時間: 2023-07-24 01:39:05

A. SQLAlchemy 中的 Session、sessionmaker、scoped_session

目錄


Session 其實 就是一個會話, 可以和資料庫打交道的一個會話

在一般的意義上, 會話建立與資料庫的所有對話,並為你在其生命周期中載入或關聯的所有對象表示一個「等待區」。他提供了一個入口點獲得查詢對象, 向資料庫發送查詢,使用會話對象的當前資料庫連接, 將結果行填充在對象中, 然後存儲在會話中, 在這種結構中稱為身份映射 – 這種數據結構維護了每一個副本的唯一, 這種唯一意味著一個對象只能有一個特殊的唯一主鍵。

會話以基本無狀態的形式開始,一旦發出查詢或其他對象被持久化,它就會從一個引擎申請連接資源,該引擎要麼與會話本身相關聯,要麼與正在操作的映射對象相關聯。此連接標識正在進行的事務, 在會話提交或回滾其掛起狀態之前,該事務一直有效。

會話中維護的所有變化的對象都會被跟蹤 - 在再次查詢資料庫或提交當前事務之前, 它將刷新對資料庫的所有更改, 這被稱為工作模式單元。

在使用會話時候,最重要的是要注意與它相關聯的對象是會話所持有的事務的代理對象 - 為了保持同步,有各種各樣的事件會導致對象重新訪問資料庫。可能從會話中分離對象並繼續使用他們,盡管這種做法有其局限性。但是通常來說,當你希望再次使用分離的對象時候,你會將他們與另一個會話重新關聯起來, 以便他們能夠恢復表示資料庫狀態的正常任務。

可能會將這里的session與http中的session搞混,需要注意的是,它有點用作緩存,因為它實現了 身份映射 模式,並存儲了鍵入其主鍵的對象。但是,它不執行任何類型的查詢緩存。 此外,默認情況下,Session使用弱引用存儲對象實例。這也違背了將Session用作緩存的目的。關於session強應用下次再討論。


1. session創建和管理資料庫連接的會話 2. model object 通過session對象訪問資料庫,並把訪問到的數據以 Identity Map 的方式,映射到Model object 中


1. session在剛被創建的時候,還沒有和任何model object 綁定,可認為是無狀態的 2. session 接受到query查詢語句, 執行的結果或保持或者關聯到session中 3. 任意數量的model object被創建,並綁定到session中,session會管理這些對象 4. 一旦session 裡面的objects 有變化,那可是要commit/rollback提交或者放棄changs


一般來說,session在需要訪問資料庫的時候創建,在session訪問資料庫的時候,准確來說,應該是「add/ update / delete 」資料庫的時候,會開啟 database transaction 。 假設沒有修改autocommit的默認值( False ), 那麼, database transaction 一直會保持,只有等到 session 發生rolled back、committed、或者closed的時候才結束,一般建議,當 database transaction 結束的時候,同時 close session ,以保證,每次發起請求,都會創建一個新的 session 特別是對web應用來說,發起一個請求,若請求使用到 Session 訪問資料庫,則創建 session ,處理完這個請求後,關閉 session



Session 是一個直接實例化的常規的Python 類。然而, 為了標准會會話的配置和獲取方式, sessionmaker 類通常用於創建頂級會話配置, 然後可以在整個應用程序中使用它, 就不需要重復配置參數。


下面是sessionmaker 的使用方式


在上面,該 sessionmaker()創建了一個工廠類,在創建這個工廠類時我們配置了參數綁定了引擎。將其賦值給Session。每次實例化Session都會創建一個綁定了引擎的Session。 這樣這個session在訪問資料庫時都會通過這個綁定好的引擎來獲取連接資源當你編寫應用程序時, 請將sessionmaker 工廠放在全局級別,視作應用程序配置的一部分。例如:應用程序包中有三個.py文件,您可以將該sessionmaker行放在__init__.py文件中; 在其他模塊「from mypackage import Session」。這樣,所有的Session()的配置都由該配置中心控制。

直接只用 create_engine 時,就會創建一個帶連接池的引擎:


創建一個session,連接池會分配一個connection。當session在使用後顯示地調用 session.close(),也不能把這個連接關閉,而是由由QueuePool連接池管理並復用連接。

確保 session 在使用完成後用 session.close、session.commit 或 session.rollback 把連接還回 pool,這是一個必須在意的習慣。

關於SQLAlchemy 資料庫連接池:

session 和 connection 不是相同的東西, session 使用連接來操作資料庫,一旦任務完成 session 會將資料庫 connection 交還給 pool。 在使用 create_engine 創建引擎時,如果默認不指定連接池設置的話,一般情況下,SQLAlchemy 會使用一個 QueuePool 綁定在新創建的引擎上。並附上合適的連接池參數

create_engine() 函數和連接池相關的參數有:

SQLAlchemy不使用連接池:在創建引擎時指定參數 poolclass=NullPool 即禁用了SQLAlchemy提供的資料庫連接池。SQLAlchemy 就會在執行 session.close() 後立刻斷開資料庫連接。當然,如果沒有被調用 session.close(),則資料庫連接不會被斷開,直到程序終止。



關於 SQLAlchemy 的 engine ,這里有一篇文章寫的很好: http://sunnyingit.github.io/book/section_python/SQLalchemy-engine.html

session不是線程安全的,在多線程的環境中,默認情況下,多個線程將會共享同一個session。試想一下,假設A線程正在使用session處理資料庫,B線程已經執行完成,把session給close了,那麼此時A在使用session就會報錯,怎麼避免這個問題?

1 . 可以考慮在這些線程之間共享Session及其對象。但是應用程序需要確保實現正確的鎖定方案,以便多個線程不會同時訪問Session或其狀態。SQLAlchemy 中的 scoped_session 就可以證線程安全,下面會有討論。 2 . 為每個並發線程維護一個會話,而不是將對象從一個Session復制到另一個Session,通常使用Session.merge()方法將對象的狀態復制到一個不同Session的新的本地對象中。


上面簡單介紹了sessionmaker的作用,下面開始探討 scoped_session 對創建 Session 的影響。現在先探討單線程情況。



結論:

通過 sessionmaker 工廠創建了兩個 Session ,而且可以看到 s1 s2 是兩個不同的 Session 。 在 s1 添加 person 後,繼續使用 s2 添加 person 報錯. 說 person 這個對象 已經和 另一個 Session 關聯一起來了, 所以再次關聯另一個 Session 就會報錯。


即在上面代碼的 s1.add(person) 之後, s1.commit() ,然後再 s2.add(persion)這里就沒帖代碼了。

結論:

即使在 s1 提交之後, s2 再去添加 person 也會發生錯誤,但 s1 的提交是成功了的,數據 person 已經存放在資料庫了。 當 s1 添加 person 並提交,然後關閉 s1 , s2 再去添加並提交 person 資料庫,這不會報錯,但是資料庫也不會出現兩條 person 數據。



結論:

s1 關閉之後, s2 再去添加提交同一個對象,不會報錯,但是資料庫值有一條 person 數據。



結論:

當然, s1 , s2 添加提交不同的對象,不會出錯。在資料庫成功新增數據。



以上說明:

一個對象一旦被一個 Session 添加,除非關閉這個 Session ,不然其他的 Session 無法添加這個對象。 一個 Session 添加並提交一個對象,然後關閉該 Session ,其他的 Session 可以添加並提交這個對象,但是資料庫並不會有這條數據。



結論:

可以看到,通過 scoped_session再去創建 Session ,返回的是同一個 Session 。 scoped_session類似單例模式,當我們調用使用的時候,會先在Registry里找找之前是否已經創建Session,未創建則創建 Session ,已創建則直接返回。


這里探討在多線程下使用 scoped_session 與不使用 scoped_session 的情況

當不使用 scoped_session 時,也分兩種情況,是否創建全局性 Session


結論:

每個線程下的 Session 都是不同的 Session 資料庫成功新增了線程3提交的數據,其他的線程中的數據並沒有提交到資料庫中去。




結論:

全部線程下的 Session 都時同一個 Session 每個線程下的數據都被提交到了資料庫




結論:

每個線程下的 Session 都不相同 只有線程3下的數據被提交到了資料庫






結論:

每個線程下的 Session 是同一個 Session 每個線程下的數據都沒提交到了資料庫


以上說明:

在同一個線程中,有 scoped_session 的時候,返回的是同一個 Session 對象。 在多線程下,即使通過 scoped_session 創建Session,每個線程下的 Session 都是不一樣的,每個線程都有一個屬於自己的 Session 對象,這個對象只在本線程下共享。 scoped_session 只有在單線程下才能發揮其作用。在多線程下顯得沒有什麼作用。

B. oracle 什麼是 session

session,會話。
簡單一點,每一個連接資料庫的動作都會產生一個會話。
比如有一個人通過網路客戶端連接了資料庫,那麼這就是一個會話。
一個計劃任務的運行,因為是計劃任務的內容在操作資料庫,也就相當於資料庫啟動了一個東西連接並操作資料庫,所以這也是一個session.
網頁通過jdbc的方式連接資料庫,其實也是一個會話。
對於會話資料庫會分配給一定的內存,讓他能完成一些操作,當會話斷開,這部分內存則釋放。