悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認爲別人會修改,因此每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關係型數據庫裏邊就用到了不少這種鎖機制,好比行鎖,表鎖等,讀鎖,寫鎖等,都是在作操做以前先上鎖。html
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,因此不會上鎖,可是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量,像數據庫若是提供相似於write_condition機制的其實都是提供的樂觀鎖。java
兩種鎖各有優缺點,不可認爲一種好於另外一種,像樂觀鎖適用於寫比較少的狀況下,即衝突真的不多發生的時候,這樣能夠省去了鎖的開銷,加大了系統的整個吞吐量。但若是常常產生衝突,上層應用會不斷的進行retry,這樣反卻是下降了性能,因此這種狀況下用悲觀鎖就比較合適。數據庫
悲觀鎖session
地址:http://blog.163.com/liuweiyoung@126/blog/static/1731310452013328114929783/app
樂觀鎖性能
Hibernate爲樂觀鎖提供了3中實現:測試
1. 基於versionui
2. 基於timestampthis
3. 爲遺留項目添加添加樂觀鎖spa
配置基於version的樂觀鎖:
實體:
public class Employee { private String id; private String name; private int ver; private Date addTime; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getAddTime() { return addTime; } public void setAddTime(Date addTime) { this.addTime = addTime; } public int getVer() { return ver; } public void setVer(int ver) { this.ver = ver; } }hbm.xml
<hibernate-mapping package="cn.model"> <class name="Employee" table="EMPLOYEE"> <id name="id" column="ID"> <generator class="uuid"></generator> </id> <!--version標籤用於指定表示版本號的字段信息--> <version name="ver" column="VER" type="int"></version> <!--timestamp標籤用於指定表示版本號的字段信息--> <!-- <timestamp name="updateDate"column="updateDate"></timestamp> --> <property name="name" column="NAME" type="java.lang.String"/> <property name="addTime" column="ADD_TIME" type="java.util.Date"/> </class> </hibernate-mapping>
public void saveEmployee(){ Session session=null; Transaction tran=null; try{ Employee e1=new Employee(); e1.setName("Tom"); e1.setAddTime(new Date()); Employee e2=new Employee(); e2.setName("Javck"); e2.setAddTime(new Date()); session=HibernateSessionFactory.getSession(); tran=session.beginTransaction(); session.save(e1); session.save(e2); tran.commit(); }catch(Exception e){ if(session!=null){ session.close(); } } } public void updateEmployee(){ Configuration configuration = new Configuration(); configuration.configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry(); SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); Session s1=sessionFactory.openSession(); Session s2=sessionFactory.openSession(); Employee e1=(Employee) s1.get(Employee.class, "4028826750c780f00150c780f1f10000"); Employee e2=(Employee) s2.get(Employee.class, "4028826750c780f00150c780f1f10000"); System.out.println("v1="+e1.getVer()+"--v2="+e2.getVer()); Transaction t2=s2.beginTransaction(); e2.setName("第二次修改2"); t2.commit(); System.out.println("v1="+e1.getVer()+"--v2="+e2.getVer()); Transaction t1=s1.beginTransaction(); e1.setName("第一次修改1"); t1.commit(); }
而且數據庫提交的值也是第一次提交的值版本爲3