2016-02-28 63 views
0

我有一個應用程序需要從數據庫的表中知道一些記錄的最新數量,該解決方案應該適用而不更改數據庫代碼或向其中添加觸發器或函數,所以我需要數據庫供應商獨立的解決方 我用java編寫的程序,但數據庫可能是(SQLite,MySQL,PostgreSQL或MSSQL),現在我正在這樣做: 在設置爲守護進程的單獨線程中,我的應用程序通過JDBC發送一個簡單的命令到數據庫要知道最新的記錄數與條件:在數據庫中計算特定記錄的數量

while(true){ 
      SELECT COUNT(*) FROM Mytable WHERE exited='1' 
} 

和這種編碼會導致數據庫要鎖定的,減緩了整個系統,併產生巨大的數據庫日誌它終於將關閉整個事情! 我該如何以正確的方式做到始終擁有最新數量的某些記錄,或只有在數字發生變化時纔算數?

+0

我不明白爲什麼這樣的陳述會導致巨大的數據庫日誌,但您可能能夠通過在退出時創建索引來改進系統 – Andreas

+0

在繁忙循環中查詢數據庫是一個可怕的想法。你能否改變你的代碼,以便只查詢點播計數?你的應用程序在哪裏使用計數? –

回答

2

這太長了評論。

A SELECT聲明不應該 - 本身 - 具有您所描述的行爲。例如,沒有任何記錄與SELECT。現在,可能併發的insert/update/delete語句正在進行,並且這些導致問題,因爲SELECT鎖定表。

兩個一般的事情可以做:

  1. 確保比較是同一類型的。所以,如果exited是一個數字,不要使用單引號(混合類型可能會混淆某些數據庫)。
  2. 創建索引(exited)。在基本上所有的數據庫中,這是一個單一的命令:create index idx_mytable_exited on mytable(exited)

如果鎖定和併發事務是一個問題,那麼您將需要做更多的數據庫特定的事情,以避免這個問題。

+0

另外,如果後臺線程不是自動提交,保持連接打開,並且永不提交,則打開的事務可能會導致問題。在運行「SELECT」關閉事務後調用'conn.commit()'。在沒有更新執行時調用'commit()'可能看起來違反直覺,但它是必需的。 – Andreas

+0

@Gordon Linoff 線程一直在不停地做select語句,你說這種方法是安全的?! – Leo

1

正如其他人所說的,確保exited被編入索引。另外,你可以在你的查詢上設置事務隔離來做一個「髒讀」。這向數據庫服務器指出,您不需要等待其他進程的事務提交,而是希望讀取正在由其他進程更新的行上已退出的當前值。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED是使用「髒讀」的標準語法。

相關問題