高級特性—數(shù)據(jù)庫鎖操作

2018-12-24 22:25 更新

數(shù)據(jù)庫是一個多用戶使用的共享資源,當(dāng)多個用戶并發(fā)地存取數(shù)據(jù)時(shí),在數(shù)據(jù)庫中就會產(chǎn)生多個事務(wù)同時(shí)存取同一數(shù)據(jù)的情況,若對并發(fā)操作不加以控制就可能會造成數(shù)據(jù)的錯誤讀取和存儲,破壞數(shù)據(jù)庫的數(shù)據(jù)一致性,所以說,加鎖是實(shí)現(xiàn)數(shù)據(jù)庫并發(fā)控制的一個非常重要的技術(shù);

數(shù)據(jù)庫加鎖的流程是:當(dāng)事務(wù)在對某個數(shù)據(jù)對象進(jìn)行操作前,先向系統(tǒng)發(fā)出請求對其加鎖,加鎖后的事務(wù)就對該數(shù)據(jù)對象有了一定的控制,在該事務(wù)釋放鎖之前,其他的事務(wù)不能對此數(shù)據(jù)對象進(jìn)行更新操作;

因此,JDBC模塊在數(shù)據(jù)庫查詢操作中集成了針對數(shù)據(jù)庫記錄鎖的控制能力,稱之為IDBLocker,以參數(shù)的方式使用起來同樣的簡單!

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

  • MySQL:

    IDBLocker.MYSQL:行級鎖,只有符合條件的數(shù)據(jù)被加鎖,其它進(jìn)程等待資源解鎖后再進(jìn)行操作;

  • Oracle:

    IDBLocker.ORACLE:行級鎖,只有符合條件的數(shù)據(jù)被加鎖,其它進(jìn)程等待資源解鎖后再進(jìn)行操作;

    IDBLocker.ORACLE_NOWAIT:行級鎖,不進(jìn)行資源等待,只要發(fā)現(xiàn)結(jié)果集中有些數(shù)據(jù)被加鎖,立刻返回“ORA-00054錯誤”;

  • SQL Server:

    IDBLocker.SQLSERVER_NOLOCK:不加鎖,在讀取或修改數(shù)據(jù)時(shí)不加任何鎖;

    IDBLocker.SQLSERVER_HOLDLOCK:保持鎖,將此共享鎖保持至整個事務(wù)結(jié)束,而不會在途中釋放;

    IDBLocker.SQLSERVER_UPDLOCK:修改鎖,能夠保證多個進(jìn)程能同時(shí)讀取數(shù)據(jù)但只有該進(jìn)程能修改數(shù)據(jù);

    IDBLocker.SQLSERVER_TABLOCK:表鎖,整個表設(shè)置共享鎖直至該命令結(jié)束,保證其他進(jìn)程只能讀取而不能修改數(shù)據(jù);

    IDBLocker.SQLSERVER_PAGLOCK:頁鎖;

    IDBLocker.SQLSERVER_TABLOCKX:排它表鎖,將在整個表設(shè)置排它鎖,能夠防止其他進(jìn)程讀取或修改表中的數(shù)據(jù);

  • 其它數(shù)據(jù)庫:

    可以通過IDBLocker接口自行實(shí)現(xiàn);

下面通過示例代碼展示如何使用鎖:

示例代碼一:通過EntitySQL對象傳遞鎖參數(shù);

session.find(EntitySQL.create(User.class)
        .field(Fields.create(User.FIELDS.ID, User.FIELDS.USER_NAME).excluded(true))
        .forUpdate(IDBLocker.MYSQL));

示例代碼二:通過Select查詢對象傳遞鎖參數(shù);

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);

示例代碼三:基于數(shù)據(jù)實(shí)體對象傳遞鎖參數(shù)

//
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);

注意

請謹(jǐn)慎使用數(shù)據(jù)庫鎖機(jī)制,盡量避免產(chǎn)生鎖表,以免發(fā)生死鎖情況!

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號