高階特性—資料庫鎖定操作


資料庫是一個多用戶使用的共享資源,當多個使用者並發地存取資料時,在資料庫中就會產生多個交易同時存取相同資料的情況,若對並發操作不加以控制可能會造成資料的錯誤讀取和存儲,破壞資料庫的資料一致性,所以說,加鎖是實現資料庫並發控制的一個非常重要的技術;

資料庫加鎖的流程是:當事務在對某個資料物件進行操作前,先向系統發出請求對其加鎖,加鎖後的事務就對該資料物件有了一定的控制,在該事務釋放鎖之前,其他的事務無法對此資料物件進行更新操作;

因此,JDBC模組在資料庫查詢操作中整合了針對資料庫記錄鎖定的控制能力,稱之為IDBLocker,以參數的方式使用起來同樣的簡單!

首先了解IDBLocker提供的鎖定的類型:

  • MySQL:

    IDBLocker.MYSQL:行級鎖,只有符合條件的資料被加鎖,其它進程等待資源解鎖後再進行操作;

  • #Oracle:

    IDBLocker.ORACLE:行級鎖,只有符合條件的資料被加鎖,其它進程等待資源解鎖後再進行操作;

    IDBLocker.ORACLE_NOWAIT:行級鎖,不進行資源等待,只要發現結果集中有些資料被加鎖,立刻返回「ORA-00054錯誤」;

  • SQL Server:

    IDBLocker.SQLSERVER_NOLOCK:不加鎖,在讀取或修改資料時不加任何鎖;

    IDBLocker.SQLSERVER_HOLDLOCK:保持鎖,將此共用鎖定保持至整個交易結束,而不會在途中釋放;

    IDBLocker.SQLSERVER_UPDLOCK:修改鎖,能夠保證多個進程能同時讀取資料但只有該進程能修改資料;

    IDBLocker.SQLSERVER_TABLOCK:表鎖,整個表設定共用鎖定直至該指令結束,確保其他行程只能讀取而不能修改資料;

    IDBLocker.SQLSERVER_PAGLOCK:頁鎖;

    IDBLocker.SQLSERVER_TABLOCKX:排它表鎖,將在整個表中設定排它鎖,能夠防止其他程序讀取或修改表中的資料;

  • 其它資料庫:

    可以透過IDBLocker介面自行實作;

##下面透過範例程式碼展示如何使用鎖定:

範例程式碼一:透過EntitySQL物件傳遞鎖定參數;

session.find(EntitySQL.create(User.class)
        .field(Fields.create(User.FIELDS.ID, User.FIELDS.USER_NAME).excluded(true))
        .forUpdate(IDBLocker.MYSQL));
##範例程式碼二:透過Select查詢物件傳遞鎖定參數;

Select _select = Select.create(User.class, "u")
        .field("u", "username").field("ue", "money")
        .where(Where.create(
                Cond.create().eq(User.FIELDS.ID).param("bc19f5645aa9438089c5e9954e5f1ac5")))
        .forUpdate(IDBLocker.MYSQL);

session.find(SQL.create(_select), IResultSetHandler.ARRAY);
範例程式碼三:基於資料實體物件傳遞鎖定參數

##

//
User _user = new User();
_user.setId("bc19f5645aa9438089c5e9954e5f1ac5");
//
_user.load(IDBLocker.MYSQL);

//
User _user = new User();
_user.setUsername("suninformation");
_user.setPwd(DigestUtils.md5Hex("123456"));
//
IResultSet<User> _users = _user.find(IDBLocker.MYSQL);

注意

請謹慎使用資料庫鎖定機制,盡量避免產生鎖定表,以免發生死鎖狀況!

#