2012-07-19 160 views
0

我讀過本教程:http://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html但我想我仍然錯過了一些東西。JDBC Transaction如何鎖定TRANSACTION_READ_COMMITTED隔離級別的表?

讓我們舉一個例子:

  • 線程T1都有各自的連接
  • 線程T2都有各自的連接

因此,這些線程執行事務上(的setAutoCommit(假)兩個不同的連接)。本次交易執行,對單個數據庫表,以下查詢:

  • 選擇一行讀取一個漸進的數量(PN)
  • 插入一行逐步號碼設置爲:PN ++(我所
    閱讀+1)

在此表中,進度號必須唯一(它是主鍵)。

執行JDBC事務(具有TRANSACTION_READ_COMMITTED隔離級別)避免了T1和T2讀取相同PN值的問題,並且都嘗試在表中插入相同的PN ++?表被鎖定,直到Insert被執行並且commit()被調用?

回答

1

不,爲了確保您始終擁有唯一的編號,您將需要: 1)[更好]根據DB 將DB字段更改爲標識/序列/自動編號2)使用UUID作爲標識符 3)[最差]在讀/遞增/寫序列期間鎖定行

TRANSACTION_READ_COMMITTED將只確保您只能讀取已提交給數據庫的數據。即如果你有你的

UPDATE sequence 

commit 

其他線程之間的另一個200個DB操作將無法讀取你,直到你提交更新的數據,所以實際上它會做完全相反的你想要什麼。

+0

的問題是,在我的情況下,主鍵也形成由其他兩個字段(年和月),而不是隻用逐行掃描數量,這必須是唯一的,那麼,在一個月的一年,並從零開始另一個月 – 2012-07-19 11:38:33

+1

那麼恐怕在讀取,增量,更新期間鎖定行可能是唯一的方法。 – 2012-07-19 11:41:53

0

您也可以在應用程序級別進行同步。這是可行的,只要一個應用程序中只有一個方法正在執行增量。

private **synchronized** void increment() { 
    Calendar calendar = Calendar.getInstance(); 
    int year = calendar.get(Calendar.YEAR); 
    int current = dao.getMaxNumber(year); 
    dao.insertNumber(year, current+1); 
}