javalru演算法-ag真人国际官网
❶ spring本地緩存的使用方法
我們現在在用的spring cache,可以直接看spring boot提供的緩存枚舉類,有如下這些:
ehcache:一個純java的進程內緩存框架,所以也是基於本地緩存的。(注意ehcache2.x和ehcache3.x相互不兼容)。
redis:分布式緩存,只有client-server(cs)模式,java一般使用jedis/luttuce來操縱。
hazelcast:基於內存的數據網格。雖然它基於內存,但是分布式應用程序可以使用hazelcast進行分布式緩存、同步、集群、處理、發布/訂閱消息等。
guava:它是google guava工具包中的一個非常方便易用的本地化緩存實現,基於lru(最近最少使用)演算法實現,支持多種緩存過期策略。在spring5.x以後的版本已經將他標記為過期了。
caffeine:是使用java8對guava緩存的重寫版本,在spring5中將取代了guava,支持多種緩存過期策略。
simple:使用concurrentmapcachemanager,因為不支持緩存過期時間,所以做本地緩存基本不考慮該方式。
關於分布式緩存,我們需要後面會專門討論redis的用法,這里只看本地緩存。性能從高到低,依次是caffeine,guava,concurrentmapcachemanager,其中caffeine在讀寫上都快了guava近一倍。
這里我們只討論在spring boot裡面怎麼整合使用caffeine和ehcache。
主要有以下幾個步驟:
1)加依賴包:
2)配置緩存:
這里有兩種方法,通過文件配置或者在配置類裡面配置,先看一下文件配置,我們可以寫一個properties文件,內容像這樣:
然後還要在主類中加上@enablecaching註解:
另外一種更靈活的方法是在配置類中配置:
應用類:
測試類:
導入依賴包,分為2.x版本和3.x版本。
其中2.x版本做如下導入:
3.x版本做如下導入:
導包完成後,我們使用jcachemanagerfactorybean ehcache.xml的方式配置:
參考資料:
https://blog.csdn.net/f641385712/article/details/94982916
http://www.360doc.com/content/17/1017/20/16915_695800687.shtml
❷ 如何用java實現fifo頁面置換演算法
[fifo.rar] - 操作系統中內存頁面的先進先出的替換演算法fifo
[先進先出頁面演算法程序.rar] - 分別實現最佳置換演算法(optimal)、先進先出(fifo)頁面置換演算法和最近最久未使用(lru)置換演算法,並給出各演算法缺頁次數和缺頁率。
[0022.rar] - 模擬分頁式虛擬存儲管理中硬體的地址轉換和缺頁中斷,以及選擇頁面調度演算法處理缺頁中斷
[change.rar] - 用java實現操作系統的頁面置換 其中包括 最佳置換演算法(optimal)、先進先出演算法(first-in, first-out) 、最近最久不用的頁面置換演算法(leastrecently used replacement)三種演算法的實現
[m_management.rar] - 操作系統中內存管理頁面置換演算法的模擬程序,採用的是lru置換演算法
[detail_of_44b0x_tcpip.rar] - tcpip 程序包載入到44b0x 的ads1.2工程文件的說明書。說名了載入過程的細節和如何處理演示程序和代碼。演示代碼已經上傳,大家可以搜索
[.rar] - java操作系統頁面置換演算法: (1)進先出的演算法(fifo) (2)最近最少使用的演算法(lru) (3)最佳淘汰演算法(opt) (4)最少訪問頁面演算法(lfu) (註:由本人改成改進型clock演算法) (5)最近最不經常使用演算法(nur)
❸ 如何高效使用和管理bitmap
一、圖片載入流程
首先,我們談談載入圖片的流程,項目中的該模塊處理流程如下:
1.在ui主線程中,從內存緩存中獲取圖片,找到後返回。找不到進入下一步;
2.在工作線程中,從磁碟緩存中獲取圖片,找到即返回並更新內存緩存。找不到進入下一步;
3.在工作線程中,從網路中獲取圖片,找到即返回並同時更新內存緩存和磁碟緩存。找不到顯示默認以提示。
二、內存緩存類(panomemcache)
這里使用android提供的lrucache類,該類保存一個強引用來限制內容數量,每當item被訪問的時候,此item就會移動到隊列的頭部。當cache已滿的時候加入新的item時,在隊列尾部的item會被回收。
[java] view plain print ?
public class panomemorycache {
// linkedhashmap初始容量
private static final int initial_capacity = 16;
// linkedhashmap載入因子
private static final int load_factor = 0.75f;
// linkedhashmap排序模式
private static final boolean access_order = true;
// 軟引用緩存
private static linkedhashmap
// 硬引用緩存
private static lrucache
public panomemorycache() {
// 獲取單個進程可用內存的最大值
// 方式一:使用activitymanager服務(計量單位為m)
/*int memclass = ((activitymanager) context.getsystemservice(context.activity_service)).getmemoryclass();*/
// 方式二:使用runtime類(計量單位為byte)
final int memclass = (int) runtime.getruntime().maxmemory();
// 設置為可用內存的1/4(按byte計算)
final int cachesize = memclass / 4;
mlrucache = new lrucache
@override
protected int sizeof(string key, bitmap value) {
if(value != null) {
// 計算存儲bitmap所佔用的位元組數
return value.getrowbytes() * value.getheight();
} else {
return 0;
}
}
@override
protected void entryremoved(boolean evicted, string key, bitmap oldvalue, bitmap newvalue) {
if(oldvalue != null) {
// 當硬引用緩存容量已滿時,會使用lru演算法將最近沒有被使用的圖片轉入軟引用緩存
msoftcache.put(key, new softreference
}
}
};
/*
* 第一個參數:初始容量(默認16)
* 第二個參數:載入因子(默認0.75)
* 第三個參數:排序模式(true:按訪問次數排序;false:按插入順序排序)
*/
msoftcache = new linkedhashmap
private static final long serialversionuid = 7237325113220820312l;
@override
protected boolean removeeldestentry(entry
if(size() > soft_cache_size) {
return true;
}
return false;
}
};
}
/**
* 從緩存中獲取bitmap
* @param url
* @return bitmap
*/
public bitmap getbitmapfrommem(string url) {
bitmap bitmap = null;
// 先從硬引用緩存中獲取
synchronized (mlrucache) {
bitmap = mlrucache.get(url);
if(bitmap != null) {
// 找到該bitmap之後,將其移到linkedhashmap的最前面,保證它在lru演算法中將被最後刪除。
mlrucache.remove(url);
mlrucache.put(url, bitmap);
return bitmap;
}
}
// 再從軟引用緩存中獲取
synchronized (msoftcache) {
softreference
if(bitmapreference != null) {
bitmap = bitmapreference.get();
if(bitmap != null) {
// 找到該bitmap之後,將它移到硬引用緩存。並從軟引用緩存中刪除。
mlrucache.put(url, bitmap);
msoftcache.remove(url);
return bitmap;
} else {
msoftcache.remove(url);
}
}
}
return null;
}
/**
* 添加bitmap到內存緩存
* @param url
* @param bitmap
*/
public void addbitmaptocache(string url, bitmap bitmap) {
if(bitmap != null) {
synchronized (mlrucache) {
mlrucache.put(url, bitmap);
}
}
}
/**
* 清理軟引用緩存
*/
public void clearcache() {
msoftcache.clear();
msoftcache = null;
}
}
補充一點,由於4.0平台以後對softreference類引用的對象調整了回收策略,所以該類中的軟引用緩存實際上沒什麼效果,可以去掉。2.3以前平台建議保留。
三、磁碟緩存類(panodiskcache)
五、使用decodebytearray()還是decodestream()?
講到這里,有童鞋可能會問我為什麼使用bitmapfactory.decodebytearray(data, 0, data.length, opts)來創建bitmap,而非使用bitmapfactory.decodestream(is, null, opts)。你這樣做不是要多寫一個靜態方法readinputstream()嗎?
沒錯,decodestream()確實是該使用情景下的首選方法,但是在有些情形下,它會導致圖片資源不能即時獲取,或者說圖片被它偷偷地緩存起來,交 還給我們的時間有點長。但是延遲性是致命的,我們等不起。所以在這里選用decodebytearray()獲取,它直接從位元組數組中獲取,貼近於底層 io、脫離平台限制、使用起來風險更小。
六、引入緩存機制後獲取圖片的方法
[java] view plain print ?
/**
* 載入bitmap
* @param url
* @return
*/
private bitmap loadbitmap(string url) {
// 從內存緩存中獲取,推薦在主ui線程中進行
bitmap bitmap = memcache.getbitmapfrommem(url);
if(bitmap == null) {
// 從文件緩存中獲取,推薦在工作線程中進行
bitmap = diskcache.getbitmapfromdisk(url);
if(bitmap == null) {
// 從網路上獲取,不用推薦了吧,地球人都知道~_~
bitmap = panoutils.downloadbitmap(this, url);
if(bitmap != null) {
diskcache.addbitmaptocache(bitmap, url);
memcache.addbitmaptocache(url, bitmap);
}
} else {
memcache.addbitmaptocache(url, bitmap);
}
}
return bitmap;
}
七、工作線程池化
有關多線程的切換問題以及在ui線程中執行loadbitmap()方法無效的問題,請參見另一篇博文: 使用嚴苛模式打破android4.0以上平台應用中ui主線程的「獨斷專行」。
有關工作線程的處理方式,這里推薦使用定製線程池的方式,核心代碼如下:
[java] view plain print ?
// 線程池初始容量
private static final int pool_size = 4;
private executorservice executorservice;
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
// 獲取當前使用設備的cpu個數
int cpunums = runtime.getruntime().availableprocessors();
// 預開啟線程池數目
executorservice = executors.newfixedthreadpool(cpunums * pool_size);
...
executorservice.submit(new runnable() {
// 此處執行一些耗時工作,不要涉及ui工作。如果遇到,直接轉交ui主線程
pano.setimage(loadbitmap(url));
});
...
}
我們知道,線程構造也是比較耗資源的。一定要對其進行有效的管理和維護。千萬不要隨意而行,一張圖片的工作線程不搭理也許沒什麼,當使用場景變為 listview和gridview時,線程池化工作就顯得尤為重要了。android不是提供了asynctask嗎?為什麼不用它?其實 asynctask底層也是靠線程池支持的,它默認分配的線程數是128,是遠大於我們定製的executorservice。
❹ list 、set、 map有什麼區別和聯系
1、list介面對collection進行了簡單的擴充,它的具體實現類常用的有arraylist和linkedlist。
你可以將任何東西放到一個list容器中,並在需要時從中取出。arraylist從其命名中可以看出它是一種類似數組的形式進行存儲,因此它的隨機訪問速度極快,而linkedlist的內部實現是鏈表,它適合於在鏈表中間需要頻繁進行插入和刪除操作。在具體應用時可以根據需要自由選擇。
前面說的iterator只能對容器進行向前遍歷,而listiterator則繼承了iterator的思想,並提供了對list進行雙向遍歷的方法。
2、set介面也是collection的一種擴展,而與list不同的時,在set中的對象元素不能重復,也就是說你不能把同樣的東西兩次放入同一個set容器中。它的常用具體實現有hashset和treeset類。
hashset能快速定位一個元素,但是你放到hashset中的對象需要實現hashcode()方法,它使用了前面說過的哈希碼的演算法。而treeset則將放入其中的元素按序存放,這就要求你放入其中的對象是可排序的,這就用到了集合框架提供的另外兩個實用類comparable和comparator。
一個類是可排序的,它就應該實現comparable介面。有時多個類具有相同的排序演算法,那就不需要在每分別重復定義相同的排序演算法,只要實現comparator介面即可。
集合框架中還有兩個很實用的公用類:collections和arrays。collections提供了對一個collection容器進行諸如排序、復制、查找和填充等一些非常有用的方法,arrays則是對一個數組進行類似的操作。
3、map是一種把鍵對象和值對象進行關聯的容器,而一個值對象又可以是一個map,依次類推,這樣就可形成一個多級映射。
對於鍵對象來說,像set一樣,一個map容器中的鍵對象不允許重復,這是為了保持查找結果的一致性;如果有兩個鍵對象一樣,那你想得到那個鍵對象所對應的值對象時就有問題了,可能你得到的並不是你想的那個值對象,結果會造成混亂,所以鍵的唯一性很重要,也是符合集合的性質的。
當然在使用過程中,某個鍵所對應的值對象可能會發生變化,這時會按照最後一次修改的值對象與鍵對應。對於值對象則沒有唯一性的要求。你可以將任意多個鍵都映射到一個值對象上,這不會發生任何問題(不過對你的使用卻可能會造成不便,你不知道你得到的到底是那一個鍵所對應的值對象)。
map有兩種比較常用的實現:hashmap和treemap。hashmap也用到了哈希碼的演算法,以便快速查找一個鍵,treemap則是對鍵按序存放,因此它便有一些擴展的方法,比如firstkey(),lastkey()等,你還可以從treemap中指定一個范圍以取得其子map。
鍵和值的關聯很簡單,用pub(object key,object value)方法即可將一個鍵與一個值對象相關聯。用get(object key)可得到與此key對象所對應的值對象
(4)javalru演算法擴展閱讀:
解疑:
1、什麼是iterator
一些集合類提供了內容遍歷的功能,通過java.util.iterator介面。這些介面允許遍歷對象的集合。依次操作每個元素對象。當使用 iterators時,在獲得iterator的時候包含一個集合快照。通常在遍歷一個iterator的時候不建議修改集合本省。
2、iterator與listiterator有什麼區別?
iterator:只能正向遍歷集合,適用於獲取移除元素。listierator:繼承iterator,可以雙向列表的遍歷,同樣支持元素的修改。
3、什麼是haspmap和map?
map是介面,java 集合框架中一部分,用於存儲鍵值對,hashmap是用哈希演算法實現map的類。
4、hashmap與hashtable有什麼區別?對比hashtable vs hashmap
兩者都是用key-value方式獲取數據。hashtable是原始集合類之一(也稱作遺留類)。hashmap作為新集合框架的一部分在java2的1.2版本中加入。它們之間有一下區別:
● hashmap和hashtable大致是等同的,除了非同步和空值(hashmap允許null值作為key和value,而hashtable不可以)。
● hashmap沒法保證映射的順序一直不變,但是作為hashmap的子類linkedhashmap,如果想要預知的順序迭代(默認按照插入順序),你可以很輕易的置換為hashmap,如果使用hashtable就沒那麼容易了。
● hashmap不是同步的,而hashtable是同步的。
● 迭代hashmap採用快速失敗機制,而hashtable不是,所以這是設計的考慮點。
5、在hashtable上下文中同步是什麼意思?
同步意味著在一個時間點只能有一個線程可以修改哈希表,任何線程在執行hashtable的更新操作前需要獲取對象鎖,其他線程等待鎖的釋放。
6、什麼叫做快速失敗特性
從高級別層次來說快速失敗是一個系統或軟體對於其故障做出的響應。一個快速失敗系統設計用來即時報告可能會導致失敗的任何故障情況,它通常用來停止正常的操作而不是嘗試繼續做可能有缺陷的工作。當有問題發生時,快速失敗系統即時可見地發錯錯誤告警。
在java中,快速失敗與iterators有關。如果一個iterator在集合對象上創建了,其它線程欲「結構化」的修改該集合對象,並發修改異常 () 拋出。
7、怎樣使hashmap同步?
hashmap可以通過map m = collections.synchronizedmap(hashmap)來達到同步的效果。
8、什麼時候使用hashtable,什麼時候使用hashmap
基本的不同點是hashtable同步hashmap不是的,所以無論什麼時候有多個線程訪問相同實例的可能時,就應該使用hashtable,反之使用hashmap。非線程安全的數據結構能帶來更好的性能。
如果在將來有一種可能—你需要按順序獲得鍵值對的方案時,hashmap是一個很好的選擇,因為有hashmap的一個子類 linkedhashmap。所以如果你想可預測的按順序迭代(默認按插入的順序),你可以很方便用linkedhashmap替換hashmap。
反觀要是使用的hashtable就沒那麼簡單了。同時如果有多個線程訪問hashmap,collections.synchronizedmap()可以代替,總的來說hashmap更靈活。
9、為什麼vector類認為是廢棄的或者是非官方地不推薦使用?或者說為什麼我們應該一直使用arraylist而不是vector
你應該使用arraylist而不是vector是因為默認情況下你是非同步訪問的,vector同步了每個方法,你幾乎從不要那樣做,通常有想要同步的是整個操作序列。同步單個的操作也不安全(如果你迭代一個vector,你還是要加鎖,以避免其它線程在同一時刻改變集合)。
而且效率更慢。當然同樣有鎖的開銷即使你不需要,這是個很糟糕的方法在默認情況下同步訪問。你可以一直使用collections.sychronizedlist來裝飾一個集合。
事實上vector結合了「可變數組」的集合和同步每個操作的實現。這是另外一個設計上的缺陷。vector還有些遺留的方法在枚舉和元素獲取的方法,這些方法不同於list介面,如果這些方法在代碼中程序員更趨向於想用它。
盡管枚舉速度更快,但是他們不能檢查如果集合在迭代的時候修改了,這樣將導致問題。盡管以上諸多原因,oracle也從沒宣稱過要廢棄vector。
❺ 創建一個序列,第一次從5循環到10,以後再從0開始循環。如果數據的控制文件損壞了,需要如何解決故障。
1、 oracle 實例――包括內存結構與後台進程 2、 oracle 資料庫――物理操作系統文件的集合 3、 了解內存結構的組成 4、 了解後台進程的作用
1、 oracle 實例――包括內存結構與後台進程
2、 oracle 資料庫――物理操作系統文件的集合
3、 了解內存結構的組成
4、 了解後台進程的作用
5、 了解資料庫的物理文件
6、 解釋各種邏輯結構
一、oracle實例
1、oracle 實例
system global area(sga) 和 background process 稱為資料庫的實例。
2、oracle 資料庫
一系列物理文件的集合(數據文件,控制文件,聯機日誌,參數文件等)
3、系統全局共享區system global area(sga)
system global area 是一塊巨大的共享內存區域,他被看做是oracle 資料庫的一個大緩沖池,這里的數據可以被oracle的各個進程共用。其大小可以通過如下語句查看:
sql> select * from v$sga;
name value
-------------------- ---------
fixed size 39816
variable size 259812784
database buffers 1.049e 09
redo buffers 327680
更詳細的信息可以參考v$sgastat、v$buffer_pool
主要包括以下幾個部分:
a、 共享池(shared pool)
共享池是sga中最關鍵的內存片段,特別是在性能和可伸縮性上。一個太小的共享池會扼殺性能,使系統停止,太大的共享池也會有同樣的效果,將會消耗大量的cpu來管理這個共享池。不正確的使用共享池只會帶來災難。共享池主要又可以分為以下兩個部分:
sql語句緩沖(library cache)
當一個用戶提交一個sql語句,oracle會將這句sql進行分析(parse),這個過程類似於編譯,會耗費相對較多的時間。在分析完這個sql,oracle會把他的分析結果給保存在shared pool的library cache中,當資料庫第二次執行該sql時,oracle自動跳過這個分析過程,從而減少了系統運行的時間。這也是為什麼第一次運行的sql 比第二次運行的sql要慢一點的原因。
下面舉例說明parse的時間
sql> select count(*) fromscpass ;
count(*)
----------
243
elapsed: 00:00:00.08
這是在share_pool 和data buffer 都沒有數據緩沖區的情況下所用的時間
sql> alter system flush shared_pool;
system altered.
清空share_pool,保留data buffer
sql> select count(*) from scpass ;
count(*)
----------
243
elapsed: 00:00:00.02
sql> select count(*) from scpass ;
count(*)
----------
243
elapsed: 00:00:00.00
從兩句sql 的時間差上可以看出該sql 的parse 時間約為00:00:00.02
對於保存在共享池中的sql語句,可以從v$sqltext、v$sqlarea中查詢到,對於編程者來說,要盡量提高語句的重用率,減少語句的分析時間。一個設計的差的應用程序可以毀掉整個資料庫的share pool,提高sql語句的重用率必須先養成良好的變成習慣,盡量使用bind變數。
數據字典緩沖區(data dictionary cache)
顯而易見,數據字典緩沖區是oracle特地為數據字典准備的一塊緩沖池,供oracle內部使用,沒有什麼可以說的。
b、塊緩沖區高速緩存(database buffer cache)
這些緩沖是對應所有數據文件中的一些被使用到的數據塊。讓他們能夠在內存中進行操作。在這個級別里沒有系統文件,,戶數據文件,臨時數據文件,回滾段文件之分。也就是任何文件的數據塊都有可能被緩沖。資料庫的任何修改都在該緩沖里完成,並由dbwr進程將修改後的數據寫入磁碟。
這個緩沖區的塊基本上在兩個不同的列表中管理。一個是塊的「臟」表(dirty list),需要用資料庫塊的
書寫器(dbwr)來寫入,另外一個是不臟的塊的列表(free list),一般的情況下,是使用最近最少使用 (least recently used,lru)演算法來管理。塊緩沖區高速緩存又可以細分為以下三個部分(default pool,keep pool,recycle pool)。如果不是人為設置初始化參數(init.ora),oracle將默認為default pool。由於操作系統定址能力的限制,不通過特殊設置,在32位的系統上,塊緩沖區高速緩存最大可以達到1.7g,在64位系統上,塊緩沖區高速緩存最大可以達到10g。
c、重做日誌緩沖區(redo log buffer)
重做日誌文件的緩沖區,對資料庫的任何修改都按順序被記錄在該緩沖,然後由lgwr進程將它寫入磁碟。這些修改信息可能是dml語句,如(insert,update,delete),或ddl語句,如(create,alter,drop等)。 重做日誌緩沖區的存在是因為內存到內存的操作比較內存到硬碟的速度快很多,所以重作日誌緩沖區可以加快資料庫的操作速度,但是考慮的資料庫的一致性與可恢復性,數據在重做日誌緩沖區中的滯留時間不會很長。所以重作日誌緩沖區一般都很小,大於3m之後的重作日誌緩沖區已經沒有太大的實際意義。
d、java程序緩沖區(java pool)
java 的程序區,oracle 8i 以後,oracle 在內核中加入了對java的支持。該程序緩沖區就是為java 程序保留的。如果不用java程序沒有必要改變該緩沖區的默認大小。
e、大池(large pool)
大池的得名不是因為大,而是因為它用來分配大塊的內存,處理比共享池更大的內存,在8.0開始引入。
下面對象使用大池:
mts――在sga的large pool中分配uga
語句的並行查詢(parallel executeion of statements)――允許進程間消息緩沖區的分配,用來協調 並行查詢伺服器
備份(backup)――用於rman磁碟i/o緩存
4、後台進程(background process)
後台進程是oracle的程序,用來管理資料庫的讀寫,恢復和監視等工作。server process主要是通過他和user process進行聯系和溝通,並由他和user process進行數據的交換。在unix機器上,oracle後台進程相對於操作系統進程,也就是說,一個oracle後台進程將啟動一個操作系統進程;在windows機器上, oracle後台進程相對於操作系統線程,打開任務管理器,我們只能看到一個oracle.exe的進程,但是通過另外的工具,就可以看到包含在這里進程中的線程。
在unix上可以通過如下方法查看後台進程:
ps ?ef | grep ora_
# ps -ef | grep ora_ | grep xcluat
oracle 29431 1 0 sep 02 2:02 ora_dbwr_sid
oracle 29444 1 0 sep 02 0:03 ora_ckpt_sid
oracle 29448 1 0 sep 02 2:42 ora_smon_sid
oracle 29442 1 0 sep 02 3:25 ora_lgwr_sid
oracle 29427 1 0 sep 02 0:01 ora_pmon_sid
a、oracle系統有5 個基本進程他們是
dbwr(數據文件寫入進程)
lgwr(日誌文件寫入進程)
smon(系統監護進程)
pmon(用戶進程監護進程)
ckpt(檢查點進程,同步數據文件, 日誌文件,控制文件)
b、dbwr
將修改過的數據緩沖區的數據寫入對應數據文件
維護系統內的空緩沖區
這里指出幾個容易錯誤的概念:
當一個更新提交後,dbwr把數據寫到磁碟並返回給用戶提交完成.
dbwr會觸發ckpt 後台進程
dbwr不會觸發lgwr 進程
上面的概念都是錯誤的.
dbwr是一個很底層的工作進程,他批量的把緩沖區的數據寫入磁碟。和任何前台用戶的進程幾乎沒有什麼關系,也不受他們的控制。至於dbwr會不會觸發lgwr和ckpt進程,我們將在下面幾節里討論。
dbwr工作的主要條件如下
dbwr 超時
系統中沒有多的空緩沖區用來存放數據
ckpt 進程觸發dbwr 等
c、lgwr
將重做日誌緩沖區的數據寫入重做日誌文件,lgwr是一個必須和前台用戶進程通信的進程。當數據被修改的時候,系統會產生一個重做日誌並記錄在重做日誌緩沖區內。這個重做日誌可以類似的認為是以下的一個結構:
scn=000000001000
數據塊id
對象id=0801
數據行=02
修改後的數據=0011
提交的時候,lgwr必須將被修改的數據的重做日誌緩沖區內數據寫入日誌數據文件,然後再通知前台進程提交成功,並由前台進程通知用戶。從這點可以看出lgwr承擔了維護系統數據完整性的任務。
lgwr 工作的主要條件如下
用戶提交
有1/3 重做日誌緩沖區未被寫入磁碟
有大於1m 重做日誌緩沖區未被寫入磁碟
超時
dbwr需要寫入的數據的scn號大於lgwr 記錄的scn號,dbwr 觸發lgwr寫入
d、smon
工作主要包含
清除臨時空間
在系統啟動時,完成系統實例恢復
聚結空閑空間
從不可用的文件中恢復事務的活動
ops中失敗節點的實例恢復
清除obj$表
縮減回滾段
使回滾段離線
e、pmon
主要用於清除失效的用戶進程,釋放用戶進程所用的資源。如pmon將回滾未提交的工作,釋放鎖,釋放分配給失敗進程的sga資源。
f、ckpt
同步數據文件,日誌文件和控制文件,由於dbwr/lgwr的工作原理,造成了數據文件,日誌文件,控制文件的不一至,這就需要ckpt進程來同步。ckpt會更新數據文件/控制文件的頭信息。
ckpt工作的主要條件如下
在日誌切換的時候
資料庫用immediate ,transaction , normal 選項shutdown 資料庫的時候
根據初始話文件log_checkpoint_interval、log_checkpoint_timeout、fast_start_io_target 的設置的數值來確定
用戶觸發
以下進程的啟動需要手工配置
g、arch
當資料庫以歸檔方式運行的時候,oracle會啟動arch進程,當重做日誌文件被寫滿時,日誌文件進行切換,舊的重做日誌文件就被arch進程復制到一個/多個特定的目錄/遠程機器。這些被復制的重做日誌文件被叫做歸檔日誌文件。
h、reco
負責解決分布事物中的故障。oracle可以連接遠程的多個資料庫,當由於網路問題,有些事物處於懸而未決的狀態。reco進程試圖建立與遠程伺服器的通信,當故障消除後,reco進程自動解決所有懸而未決的會話。
i、服務進程server process
服務進程的分類
專用服務進程(dedicated server process)
一個服務進程對應一個用戶進程
共享服務進程(multitreaded server process)
一個服務進程對應多個用戶進程,輪流為用戶進程服務。
pga & uga
pga = process global area
uga = user global area
他保存了用戶的變數、許可權、堆棧、排序空間等用戶信息,對於專用伺服器進程,uga在pga中分配。對於多線程進程,uga在large pool中分配。
j、用戶進程user process
在客戶端,將用戶的sql 語句傳遞給服務進程
5、一個貫穿資料庫全局的概念----系統改變號scn(system change number)
系統改變號,一個由系統內部維護的序列號。當系統需要更新的時候自動增加,他是系統中維持數據的一致性和順序恢復的重要標志。
a. 查詢語句不會使scn增加,就算是同時發生的更新,資料庫內部對應的scn也是不同的。這樣一來就保證了數據恢復時候的順序。
b. 維持數據的一致性,當一
二、oracle 資料庫
oracle資料庫的組成――物理操作系統文件的集合。主要包括以下幾種。
1、控制文件(參數文件init.ora記錄了控制文件的位置)
控制文件包括如下主要信息
資料庫的名字,檢查點信息,資料庫創建的時間戳
所有的數據文件,聯機日誌文件,歸檔日誌文件信息
備份信息等
有了這些信息,oracle就知道那些文件是數據文件,現在的重做日誌文件是哪些,這些都是系統啟動和運行的基本條件,所以他是oracle運行的根本。如果沒有控制文件系統是不可能啟動的。控制文件是非常重要的,一般採用多個鏡相復制來保護控制文件,或採用raid來保護控制文件。控制文件的丟失,將使資料庫的恢復變的很復雜。
控制文件信息可以從v$controlfile中查詢獲得
2、數據文件(數據文件的詳細信息記載在控制文件中)
可以通過如下方式查看數據文件
sql> select name from v$datafile;
name
---------------------------------------------
/u05/dbf/prod/system_01.dbf
/u06/dbf/prod/temp_01.dbf
/u04/dbf/prod/users_01.dbf
/u09/dbf/prod/rbs_01.dbf
/u06/dbf/prod/applsys_indx_01.dbf
/u05/dbf/prod/applsys_data_01.dbf
從以上可以看出,數據文件大致可以分為以下幾類:
i. 系統數據文件(system_01.dbf)
存放系統表和數據字典,一般不放用戶的數據,但是用戶腳本,如過程,函數,包等卻是保存在數據字典中的。
名詞解釋:數據字典 數據字典是一些系統表或視圖,他存放系統的信息,他包括資料庫版本,數據文件信息,表與索引等段信息,系統的運行狀態等各種和系統有關的信息和用戶腳本信息。資料庫管理員可以通過對數據字典的查詢,就可以了解到oracle的運行狀態。
ii. 回滾段文件(rbs_01.dbf)
如果資料庫進行對數據的修改,那麼就必須使用回滾段,回滾段是用來臨時存放修改前的數據(before image)。回滾段通常都放在一個單獨的表空間上(回滾表空間),避免表空間碎片化,這個表空間包含的數據文件就是回滾數據文件。
iii. 臨時數據文件(temp_01.dbf)
主要存放用戶的排序等臨時數據,與回滾段相似,臨時段也容易引起表空間碎片化,而且沒有辦法在一個永久表空間上開辟臨時段,所以就必須有一個臨時表空間,它所包含的數據文件就是臨時數據文件,主要用於不能在內存上進行的排序操作。我們必須為用戶指定一個臨時表空間。
iv. 用戶數據文件(/applsys_data_01.dbf ,applsys_indx_01.dbf)
存放用戶數據,這里列舉了兩類常見的用戶型數據,一般數據和索引數據,一般來說,如果條件許可的話,可以考慮放在不同的磁碟上。
3、重做日誌文件(聯機重做日誌)
用戶對資料庫進行的任何操作都會記錄在重做日誌文件。在了解重做日誌之前必須了解重做日誌的兩個概念,重做日誌組和重做日誌組成員(member),一個資料庫中至少要有兩個日誌組文件,一組寫完後再寫另一組,即輪流寫。每個日誌組中至少有一個日誌成員,一個日誌組中的多個日誌成員是鏡相關系,有利於日誌文件的保護,因為日誌文件的損壞,特別是當前聯機日誌的損壞,對資料庫的影響是巨大的。
聯機日誌組的交換過程叫做切換,需要特別注意的是,日誌切換在一個優化效果不好的資料庫中會引起臨時的「掛起」。掛起大致有兩種情況:
在歸檔情況下,需要歸檔的日誌來不及歸檔,而聯機日誌又需要被重新利用
檢查點事件還沒有完成(日誌切換引起檢查點),而聯機日誌需要被重新利用
解決這種問題的常用手段是:
i.增加日誌組
ii.增大日誌文件成員大小
通過v$log可以查看日誌組,v$logfile可以查看具體的成員文件。
4、歸檔日誌文件
oracle可以運行在兩種模式之中,歸檔模式和不歸檔模式。如果不用歸檔模式,當然,你就不會有歸檔日誌,但是,你的系統將不會是一個實用系統,特別是不能用於生產系統,因為你可能會丟失數據。但是在歸檔模式中,為了保存用戶的所有修改,在重做日誌文件切換後和被覆蓋之間系統將他們另外保存成一組連續的文件系列,該文件系列就是歸檔日誌文件。
有人或許會說,歸檔日誌文件佔領我大量的硬碟空間,其實,具體想一想,你是願意浪費一點磁碟空間來保護你的數據,還是願意丟失你的數據呢?顯而義見,我們需要保證我們的數據的安全性。其實,歸檔並不是一直佔領你的磁碟空間,你可以把她備份到磁帶上,或則刪除上一次完整備份前的所有日誌文件。
5、初始化參數文件
initsid.ora或init.ora文件,因為版本的不一樣,其位置也可能會不一樣。在8i中,通常位於$oracle_home/admin//pfile下,初始化文件記載了許多資料庫的啟動參數,如內存,控制文件,進程數等,在資料庫啟動的時候載入(nomount時載入),初始化文件記錄了很多重要參數,對資料庫的性能影響很大,如果不是很了解,不要輕易亂改寫,否則會引起資料庫性能下降。
6、其他文件
i . 密碼文件
用於oracle 的具有sysdba許可權用戶的認證.
ii. 日誌文件
報警日誌文件(alert.log或alrt.ora)
記錄資料庫啟動,關閉和一些重要的出錯信息。資料庫管理員應該經常檢查這個文件,並對出現的問題作出即使的反應。你可以通過以下sql 找到他的路徑select value from v$parameter where name ="background_mp_dest";
後台或用戶跟蹤文件
系統進程或用戶進程出錯前寫入的信息,一般不可能讀懂,可以通過oracle的tkprof工具轉化為可以讀懂的格式。對於系統進程產生的跟蹤文件與報警日誌文件的路徑一樣,用戶跟蹤文件的路徑,你可以通過以下sql找到他的路徑select value from v$parameter where name ="user_mp_dest";
三、oracle邏輯結構
1、 表空間(tablespace)
表空間是資料庫中的基本邏輯結構,一系列數據文件的集合。一個表空間可以包含多個數據文件,但是一個數據文件只能屬於一個表空間。
2、 段(segment)
段是對象在資料庫中佔用的空間,雖然段和資料庫對象是一一對應的,但段是從資料庫存儲的角度來看的。一個段只能屬於一個表空間,當然一個表空間可以有多個段。
表空間和數據文件是物理存儲上的一對多的關系,表空間和段是邏輯存儲上的一對多的關系,段不直接和數據文件發生關系。一個段可以屬於多個數據文件,關於段可以指定擴展到哪個數據文件上面。
段基本可以分為以下四種
數據段(data segment)
索引段(index segment)
回滾段(rollback segment)
臨時段(temporary segment)
3、區間(extent)
關於extent的翻譯有多種解釋,有的譯作擴展,有的譯作盤區,我這里通常譯為區間。在一個段中可以存在多個區間,區間是為數據一次性預留的一個較大的存儲空間,直到那個區間被用滿,資料庫會繼續申請一個新的預留存儲空間,即新的區間,一直到段的最大區間數(max extent)或沒有可用的磁碟空間可以申請。 在oracle8i以上版本,理論上一個段可以無窮個區間,但是多個區間對oracle卻是有性能影響的,oracle建議把數據分布在盡量少的區間上,以減少oracle的管理與磁頭的移動。
4、oracle數據塊(block)
oracle最基本的存儲單位,他是os數據塊的整數倍。oracle的操作都是以塊為基本單位,一個區間可以包含多個塊(如果區間大小不是塊大小的整數倍,oracle實際也擴展到塊的整數倍)。
5、基本表空間介紹
a. 系統表空間
主要存放數據字典和內部系統表基表
查看數據數據字典的sql
select * from dict
查看內部系統表的sql
select * from v$fixed_view_definition
dba對系統的系統表中的數據字典必須有一個很深刻的了解,他們必須准備一些基礎的sql語句,通過這些sql可以立即了解系統的狀況和資料庫的狀態,這些基本的sql包括
系統的剩餘空間
系統的sga
狀態系統的等待
用戶的許可權
當前的用戶鎖
緩沖區的使用狀況等
在成為dba 的道路上我們不建議你過分的依賴於oem/quest 等優秀的資料庫管理工具,因為他們不利於你對數據數據字典的理解,sql語句可以完成幾乎全部的資料庫管理工作。
大量的讀少量的寫是該表空間的一個顯著的特點。
b. 臨時表空間.
臨時表空間顧名思義是用來存放臨時數據的,例如排序操作的臨時空間,他的空間會在下次系統啟動的時候全部被釋放。
c. 回滾段表空間
i. 回滾段在系統中的作用
當資料庫進行更新插入刪除等操作的時候,新的數據被更新到原來的數據文件,而舊的數據(before image)就被放到回滾段中,如果數據需要回滾,那麼可以從回滾段將數據再復制到數據文件中。來完成數據的回滾。在系統恢復的時候, 回滾段可以用來回滾沒有被commit 的數據,解決系統的一至性。
回滾段在什麼情況下都是大量的寫,一般是少量讀,因此建議把回滾段單獨出來放在一個單獨的設備(如單獨的磁碟或raid),以減少磁碟的io爭用。
ii. 回滾段的工作方式
一個回滾表空間可以被劃分成多個回滾段.
一個回滾段可以保存多個會話的數據.
回滾段是一個圓形的數據模型
假設回滾段由4 個區間組成,他們的使用順序就是區間1à區間2à區間3à區間4à區間1。也就是說,區間是可以循環使用的,當區間4到區間1的時候,區間1裡面的會話還沒有結束, 區間4用完後就不能再用區間1,這時系統必須分配區間5,來繼續為其他會話服務服務。
我們分析一個update 語句的完成
①. 用戶提交一個update 語句
②. server process 檢查內存緩沖.
如果沒有該數據塊的緩沖,則從磁碟讀入
i. 如果沒有內存的有效空間,dbwr被啟動將未寫入磁碟的臟緩沖寫入磁碟
ii. 如果有有效空間,則讀入
③. 在緩沖內更新數據
i. 申請一個回滾段入口,將舊數據寫如回滾段
ii. 加鎖並更新數據
iii. 並在同時將修改記錄在redo log buffer中
另外,站長團上有產品團購,便宜有保證
❻ 簡要說明oracle資料庫體系的內存結構
內存結構 oracle內存結構大致具有四個區:軟體代碼區、系統全局區、程序全局區和排序區。 1、系統全局區。(sga) 系統全局區為一組由oracle分配的共享數據結構,它是實例的主要部分,它含有數據維護、sql語句分析與重做緩存所必須的所有內存結構,系統全局區的數據是共享的,也就是說,多個進程可以在同一時間對sga中的數據進行訪問和修改。它包含以下內容: <1>、數據塊緩沖區 該區存放最近使用過的數據塊,使用lru(最近最少使用演算法)進行管理。 <2>、字典緩沖區 該區用於保存數據字典中的行,數據字典中存放oracle系統管理自身所需的所有信息。該區也使用lru演算法管理。 <3>、重做日誌緩沖區 任何事務在記錄到重做日誌之前都先放到該區,資料庫系統定期將該區內容寫入到聯機重做日誌中。 <4>、sql共享池 存放所有通過sql語法分析、准備執行的sql語句。 <5>、java池 為java命令提供語法分析。 <6>、多緩沖池 可以在sga中創建多個緩沖池,能夠用多個緩沖池把的數據集與其他的應用程序分開,以減少它們爭奪數據塊緩沖區相同資源的可 能性。 2、程序全局區(pga) 包含單個伺服器進程或單個後台進程的數據和控制信息,與幾個進程共享的sga 正相反pga 是只被一個進程使用的區域,pga 在創建進程時分配在終止進程時回收。 3、排序區 排序需要內存,這部分空間成為排序區,排序區存在於請求排序的用戶進程的內存中,該空間的大小為適應排序數據量的大小,可增長,但受初始化參數sort_area_sizer所限制。 4、軟體代碼區 用於存儲正在執行或可以執行的程序代碼。