服務(wù)器優(yōu)化
1.緩存 用空間換時(shí)間
2.能夠稍后做的操作都推遲做,不要馬上處理 用消息隊(duì)列 等服務(wù)器空閑,再一個(gè)個(gè)取出來解決
事務(wù)
事務(wù)的ACID
- 原子性(Atomic):事務(wù)中各項(xiàng)操作,要么全做要么全不做,任何一項(xiàng)操作的失敗都會(huì)導(dǎo)致整個(gè)事務(wù)的失敗;
- 一致性(Consistent):事務(wù)結(jié)束后系統(tǒng)狀態(tài)是一致的;
- 隔離性(Isolated):并發(fā)執(zhí)行的事務(wù)彼此無法看到對(duì)方的中間狀態(tài);
- 持久性(Durable):事務(wù)完成后所做的改動(dòng)都會(huì)被持久化,即使發(fā)生災(zāi)難性的失敗。通過日志和同步備份可以在故障發(fā)生后重建數(shù)據(jù)。
補(bǔ)充:關(guān)于事務(wù),首先需要知道的是,只有存在并發(fā)數(shù)據(jù)訪問時(shí)才需要事務(wù)。當(dāng)多個(gè)事務(wù)訪問同一數(shù)據(jù)時(shí),可能會(huì)存在5類問題,包括3類數(shù)據(jù)讀取問題(臟讀、不可重復(fù)讀和幻讀)和2類數(shù)據(jù)更新問題(第1類丟失更新和第2類丟失更新)。
臟讀(Dirty Read):A事務(wù)讀取B事務(wù)尚未提交的數(shù)據(jù)并在此基礎(chǔ)上操作,而B事務(wù)執(zhí)行回滾,那么A讀取到的數(shù)據(jù)就是臟數(shù)據(jù)。
時(shí)間 | 轉(zhuǎn)賬事務(wù)A | 取款事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為1000元 | |
T4 | 取出500元余額修改為500元 | |
T5 | 查詢賬戶余額為500元(臟讀) | |
T6 | 撤銷事務(wù)余額恢復(fù)為1000元 | |
T7 | 匯入100元把余額修改為600元 | |
T8 | 提交事務(wù) |
不可重復(fù)讀(Unrepeatable Read):事務(wù)A重新讀取前面讀取過的數(shù)據(jù),發(fā)現(xiàn)該數(shù)據(jù)已經(jīng)被另一個(gè)已提交的事務(wù)B修改過了。
時(shí)間 | 轉(zhuǎn)賬事務(wù)A | 取款事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為1000元 | |
T4 | 查詢賬戶余額為1000元 | |
T5 | 取出100元修改余額為900元 | |
T6 | 提交事務(wù) | |
T7 | 查詢賬戶余額為900元(不可重復(fù)讀) |
幻讀(Phantom Read):事務(wù)A重新執(zhí)行一個(gè)查詢,返回一系列符合查詢條件的行,發(fā)現(xiàn)其中插入了被事務(wù)B提交的行。
時(shí)間 | 轉(zhuǎn)賬事務(wù)A | 取款事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 統(tǒng)計(jì)總存款為10000元 | |
T4 | 新增一個(gè)存款賬戶存入100元 | |
T5 | 提交事務(wù) | |
T6 | 再次統(tǒng)計(jì)總存款為10100元(幻讀) |
第1類丟失更新:事務(wù)A撤銷時(shí),把已經(jīng)提交的事務(wù)B的更新數(shù)據(jù)覆蓋了。
時(shí)間 | 轉(zhuǎn)賬事務(wù)A | 取款事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為1000元 | |
T4 | 查詢賬戶余額為1000元 | |
T5 | 匯入100元修改余額為1100元 | |
T6 | 提交事務(wù) | |
T7 | 取出100元將余額修改為900元 | |
T8 | 撤銷事務(wù) | |
T9 | 余額恢復(fù)為1000元(丟失更新) |
第2類丟失更新:事務(wù)A覆蓋事務(wù)B已經(jīng)提交的數(shù)據(jù),造成事務(wù)B所做的操作丟失。
時(shí)間 | 轉(zhuǎn)賬事務(wù)A | 取款事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為1000元 | |
T4 | 查詢賬戶余額為1000元 | |
T5 | 取出100元將余額修改為900元 | |
T6 | 提交事務(wù) | |
T7 | 匯入100元將余額修改為1100元 | |
T8 | 提交事務(wù) | |
T9 | 查詢賬戶余額為1100元(丟失更新) |
數(shù)據(jù)并發(fā)訪問所產(chǎn)生的問題,在有些場(chǎng)景下可能是允許的,但是有些場(chǎng)景下可能就是致命的,數(shù)據(jù)庫通常會(huì)通過鎖機(jī)制來解決數(shù)據(jù)并發(fā)訪問問題,按鎖定對(duì)象不同可以分為表級(jí)鎖和行級(jí)鎖;按并發(fā)事務(wù)鎖定關(guān)系可以分為共享鎖和獨(dú)占鎖,具體的內(nèi)容大家可以自行查閱資料進(jìn)行了解。
直接使用鎖是非常麻煩的,為此數(shù)據(jù)庫為用戶提供了自動(dòng)鎖機(jī)制,只要用戶指定會(huì)話的事務(wù)隔離級(jí)別,數(shù)據(jù)庫就會(huì)通過分析SQL語句然后為事務(wù)訪問的資源加上合適的鎖,此外,數(shù)據(jù)庫還會(huì)維護(hù)這些鎖通過各種手段提高系統(tǒng)的性能,這些對(duì)用戶來說都是透明的(就是說你不用理解,事實(shí)上我確實(shí)也不知道)。ANSI/ISO SQL 92標(biāo)準(zhǔn)定義了4個(gè)等級(jí)的事務(wù)隔離級(jí)別,如下表所示:
隔離級(jí)別 | 臟讀 | 不可重復(fù)讀 | 幻讀 | 第一類丟失更新 | 第二類丟失更新 |
---|---|---|---|---|---|
READ UNCOMMITED | 允許 | 允許 | 允許 | 不允許 | 允許 |
READ COMMITTED | 不允許 | 允許 | 允許 | 不允許 | 允許 |
REPEATABLE READ | 不允許 | 不允許 | 允許 | 不允許 | 不允許 |
SERIALIZABLE | 不允許 | 不允許 | 不允許 | 不允許 | 不允許 |
需要說明的是,事務(wù)隔離級(jí)別和數(shù)據(jù)訪問的并發(fā)性是對(duì)立的,事務(wù)隔離級(jí)別越高并發(fā)性就越差。所以要根據(jù)具體的應(yīng)用來確定合適的事務(wù)隔離級(jí)別,這個(gè)地方?jīng)]有萬能的原則。
連接池
c3p0
-
導(dǎo)入jar包
c3p0-0.9.5.2.jar
hibernate-c3p0-5.2.8.Final.jar
mchange-commons-java-0.2.11.jar - hibernate.cfg.cml配置
<!-- c3p0 connection pool -->
<property name="c3p0.min_size">10</property>
<property name="c3p0.max_size">100</property>
<property name="c3p0.timeout">60</property>
<property name="c3p0.acquire_increment">20</property>
<property name="c3p0.initialPoolSize">20</property>
dataSource
二級(jí)緩存
hibernate.cfg.xml配置
<!-- Disable the second-level cache -->
<property name="cache.use_second_level_cache">true</property>
<property name="cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
ehcache.xml配置
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="300"
overflowToDisk="true"
/>
<cache name="hello"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="goodbye"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
</ehcache>
注解
@Cache(region = "hello", usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)