❶ 深入解析Oracle資料庫安全策略
Oracle是關系型資料庫管理系統,它功能強大、性能卓越,在當今大型資料庫管理系統中佔有重要地位。在正常情況下,Oracle資料庫會保證數據的安全、穩定,為用戶提供正確的數據,但由於計算機系統的故障(硬體故障、軟體故障、網路故障和系統故障)影響資料庫系統的操作,影響資料庫中數據的正確性,甚至破壞資料庫,使資料庫中全部或部分數據丟失,整個系統都將處於癱瘓狀態。因此,如何保證Oracle資料庫的安全就陵慧掘成為整個系統安全的重要組成部分。
Oracle資料庫的安全策略包括資料庫的備份和恢復、用戶角色管理。
一、資料庫備份所使用的結構
Oracle資料庫使用幾種結構來保護數據:資料庫後備、日誌、回滾段和控制文件。
1.資料庫後備是由構成Oracle資料庫的物理文件的操作系統後備所組成。當介質故障時進行資料庫恢復,利用後備文件恢復毀壞的數據文件或控制文件。
2.每一個Oracle資料庫實例都提供日誌,記錄資料庫中所作的全部修改。每一個運行的Oracle資料庫實例相應地有一個在線日誌,它與Oracle後台進程LGWR一起工作,立即記錄該實例所作的全部修改。歸檔(離線)日誌是可選擇的,一個Oracle資料庫實例一旦在線日誌填滿後,可形成在線日誌歸檔文件。歸檔的在線日誌文件被唯一標識並合並成歸檔日誌。
3.回滾段用於存儲正在進行的事務(為未提交的事務)所修改值的老值,該信息在資料庫恢復過程中用於撤消任何非提交的修改。
4.控制文件,一般用於存儲資料庫的物理結構的狀態。控制文件中某些狀態信息在實例恢復和介質恢復期間用於引導Oracle。
二、在線日誌
一個Oracle資料庫的每一實例有一個相關聯的在線日誌。一個在線日誌由多個在線日誌文件組成。在線日誌文件(online redo log file)填入日誌項(redo entry),日誌項記錄的數據用於重構對資料庫所作的全部修改。
三、歸檔日誌
Oracle要將填滿的在線日誌文件組歸檔時,則要建立歸檔日誌(archived redo log)。其對資料庫備份和恢復有下列用處:
1.資料庫後備以及在線和歸檔日誌文件,在操作系統和磁碟故障中可保證全部提交的事物可被恢復。
2.在資料庫打開和正常系統使用下,如果歸檔日誌是永久保存,在線後備可以進行和使用。
資料庫可運行在兩種不同方式下:NOARCHIVELOG方式或ARCHIVELOG方式。資料庫在NOARCHIVELOG方式下使用時,不能進行在線日誌的歸檔。如果資料庫在ARCHIVELOG方式下運行,可實施在線日誌的歸檔。
四、Oracle的備份特性
Oracle備份包括邏輯備份和物理備份。
1.邏輯備份
資料庫的邏輯備份包含讀一個資料庫記錄集和將記錄集寫入文件。
(1)輸出(Export)輸出可以是整個資料庫、指定用戶或指定表。
(2)輸入(Import)輸入將輸出建立的二進制轉儲文件讀入並執行其命令。
2.物理備份
物理備份包含拷貝構成資料庫的文件而不管其邏輯內容。
Oracle支持兩種不同類型的物理文件備份:離線備份(offline backup)和聯機備份(online backup)。
(1) 離線備份
離線備份用在當資料庫已正常關閉,資料庫處於"offline"時,要備份下列文件:
所有數據文件
所有控制文件
所有聯機日誌
init.ora(可選的)
(2) 聯機備份
聯機備份可用來備份任何運作在ARCHIVELOG方式下的資料庫。在這種方式下,聯機日誌被歸檔,在資料庫內部建立一個所有作業的完整記錄。
聯機備份過程具備強有力的功能。第一,提供了完全的時間點尺核(point-in-time)恢復。第二,在文件系統備份時允許資料庫保持打開狀態。
備份方式特性比較
五、Oracle資料庫的角色管理
Oracle資料庫系統在利用角色管理資料庫安全性方面採取的基本措施有:
通過驗證用戶名稱和口令,防止非Oracle用戶注冊到Oracle資料庫,對資料庫進行非法存取操作。
授予用戶一定的許可權,限制用戶操縱資料庫的權力。
授予用戶對資料庫實體的存取執行許可權,阻止用戶訪問非授權數據。
提供碧孫資料庫實體存取審計機制,使資料庫管理員可以監視資料庫中數據的存取情況和系統資源的使用情況。
採用視圖機制,限制存取基表的行和列集合。
六、Oracle資料庫的安全策略
由於Oracle資料庫備份有三種方式,每種方式具有不同的恢復特性,因此應集成資料庫與文件系統備份,集成邏輯備份和物理備份。
(一)、備份策略
在操作系統級別,使用大容量磁碟陣列,通過磁碟映像技術使每一個資料庫文件自動分布於每個物理磁碟。這樣,當某個磁碟出現物理損壞時,操作系統會自動引發映像磁碟來取代失效的磁碟,保證資料庫的正常運行。
在多個不同的物理磁碟上保持多個控制文件的備份。控制文件在資料庫恢復期間用於引導Oracle,因此保持多個控制文件的備份,可以確保在出現磁碟故障後,能有可用的控制文件用於資料庫恢復。
使資料庫運行在ARCHIVELOG(歸檔)方式下,歸檔日誌存放於另一映像的邏輯磁碟上。每晚進行一次聯機備份操作,備份所有數據文件、所有歸檔日誌文件、一個控制文件。每周進行一次輸出(Export)操作。
(二)、恢復策略
1.實例失敗
從實例失敗中恢復是自動進行的。實例失敗一般是由伺服器失敗引起的,當資料庫實例失敗後,重新啟動伺服器,啟動資料庫,Oracle檢查數據文件和聯機日誌文件,並把所有文件同步到同一個時間點上。
2.磁碟失敗
如果丟失的是控制文件,只要關閉資料庫,從保留有控制文件的地方拷貝一份即可。
如果丟失的是數據文件,可用前一天晚上的聯機備份進行恢復,步驟如下:
1)從備份中把丟失的文件存在原來位置。
2)載入資料庫
3)恢復資料庫
4)打開資料庫
3.錯誤刪除或修改對象
在這種情況下,一般希望能追溯返回到錯誤發生前的那個時間點上。這叫做時間點恢復。完成恢復的步驟如下:
1)從當前資料庫輸出(Export),輸入(Import)到備用資料庫,使備用資料庫與當前資料庫保持一致。
2)向前滾動備用資料庫到錯誤發生前的那個時間點。
3)從備用資料庫輸出受錯誤影響的邏輯對象。
4)使用上一步產生的輸出文件輸入那些受影響的對象到當前資料庫。
(三)、用戶角色管理
1.對所有客戶端按工作性質分類,分別授予不同的用戶角色。
2.對不同的用戶角色,根據其使用的數據源,分別授予不同的資料庫對象存取許可權。
基於以上的安全策略,可以防止非法用戶訪問資料庫,限制合法用戶操縱資料庫的許可權;可以使資料庫在故障發生後,不會丟失任何數據,並能使資料庫迅速恢復到故障發生前的那一時間點上,最大限度的保證數據的安全和整個系統的連續運行。
❷ Flink sql 知其所以然(五)| 自定義 protobuf format
protobuf 作為目前各大公司中最廣泛使用的高效的協議數據交換格式工具庫,會大量作為流式數據傳輸的序列化方式,所以在 flink sql 中如果能實現 protobuf 的 format 會非常有用( 目前社區已經有對應的實現,不過目前還沒有 merge,預計在 1.14 系列版本中能 release )。
issue 見: https://issues.apache.org/jira/browse/FLINK-18202?filter=-4&jql=project%20%3D%20FLINK%20AND%20issuetype%20%3D%20%22New%20Feature%22%20AND%20text%20~%20protobuf%20order%20by%20created%20DESC
pr 見: https://github.com/apache/flink/pull/14376
這一節主要介紹 flink sql 中怎麼自定義實現 format ,其中以最常使用的 protobuf 作為案例來介紹。
如果想在本地直接測試下:
關於為什麼選擇 protobuf 可以看這篇文章,寫的很詳細:
http://hengyunabc.github.io/thinking-about-grpc-protobuf/?utm_source=tuicool&utm_medium=referral
在實時計算的領域中,為了可讀性會選擇 json ,為了效率以及一些已經依賴了 grpc 的公司會選擇 protobuf 來做數據序列化,那麼自然而然,日誌的序列化方式也會選擇 protobuf 。
而官方目前已經 release 的版本中是沒有提供 flink sql api 的 protobuf format 的。如下圖,基於 1.13 版本。
https://ci.apache.org/projects/flink/flink-docs-release-1.13/docs/connectors/table/overview/
因此本文在介紹怎樣自定義一個 format 的同時,實現一個 protobuf format 來給大家使用。
預期效果是先實現幾種最基本的數據類型,包括 protobuf 中的 message (自定義 model)、 map (映射)、 repeated (列表)、其他基本數據類型等,這些都是我們最常使用的類型。
預期 protobuf message 定義如下:
測試數據源數據如下,博主把 protobuf 的數據轉換為 json,以方便展示,如下圖:
預期 flink sql:
數據源表 DDL:
數據匯表 DDL:
Transform 執行邏輯:
下面是我在本地跑的結果:
可以看到列印的結果,數據是正確的被反序列化讀入,並且最終輸出到 console。
目前業界可以參考的實現如下: https://github.com/maosuhan/flink-pb , 也就是這位哥們負責目前 flink protobuf 的 format。
這種實現的具體使用方式如下:
其實現有幾個特點:
[圖片上傳失敗...(image-66c35b-1644940704671)]
其實上節已經詳細描述了 flink sql 對於 sourcesinkformat 的載入機制。
如圖 serde format 是通過 TableFactoryHelper.discoverDecodingFormat 和 TableFactoryHelper.discoverEncodingFormat 創建的
所有通過 SPI 的 sourcesinkformt 插件都繼承自 Factory 。
整體創建 format 方法的調用鏈如下圖。
最終實現如下,涉及到了幾個實現類:
具體流程:
上述實現類的具體關系如下:
介紹完流程,進入具體實現方案細節:
ProtobufFormatFactory 主要創建 format 的邏輯:
resourcesMETA-INF 文件:
主要實現反序列化的邏輯:
可以注意到上述反序列化的主要邏輯就集中在 runtimeConverter 上,即 ProtobufToRowDataConverters.ProtobufToRowDataConverter 。
ProtobufToRowDataConverters.ProtobufToRowDataConverter 就是在 ProtobufToRowDataConverters 中定義的。
ProtobufToRowDataConverters.ProtobufToRowDataConverter 其實就是一個 convertor 介面:
其作用就是將 protobuf message 中的每一個欄位轉換成為 RowData 中的每一個欄位。
ProtobufToRowDataConverters 中就定義了具體轉換邏輯,如截圖所示,每一個 LogicalType 都定義了 protobuf message 欄位轉換為 flink 數據類型的邏輯:
源碼後台回復 flink sql 知其所以然(五)| 自定義 protobuf format 獲取。
本文主要是針對 flink sql protobuf format 進行了原理解釋以及對應的實現。
如果你正好需要這么一個 format,直接後台回復 flink sql 知其所以然(五)| 自定義 protobuf format 獲取源碼吧。
當然上述只是 protobuf format 一個基礎的實現,用於生產環境還有很多方面可以去擴展的。
❸ 徹底搞懂JDBC的運行過程
前幾天筆者發布了博客,手寫mybatis徹底搞懂框架原理。為了幫助初學者更好理解mybatis框架,這次講解一下Java的JDBC的運行過程。
JDBC的作用
JDBC的全稱是Java DataBase Connection,也就是Java資料庫連接,我們可以用它來操作關系型資料庫。JDBC介面及相關類在java.sql包和javax.sql包里。我們可以用它來連接資料庫,執行SQL查詢,存儲過程,並處理返回的結果。
JDBC介面讓Java程序和JDBC驅動實現了松耦合,使得切換不同的資料庫變得更加簡單。
JDBC的連接步驟
執行一次JDBC連接,分六個步驟進行:
1. 導入包
在程序中包含資料庫編程所需的JDBC類。大多數情況下,使用 import java.sql.* 就足夠了
2. 注冊JDBC驅動程序
需要初始化驅動程序,這樣就可以打開與資料庫的通信。
3. 打開一個連接
使用DriverManager.getConnection()方法來創建一個Connection對象,它代表一個資料庫的物理連接。
4. 執行一個查詢
需要使用一個類型為Statement或PreparedStatement的對象(兩者區別看後文),並提交一個SQL語句到資料庫執行查詢。
5. 從結果集中提取數據
這一步中演示如何從資料庫中獲取查詢結果的數據。使用ResultSet.getXXX()方法來檢索的數據結果
6. 清理環境資源
在使用JDBC與數據交互操作資料庫中的數據後,應該明確地關閉所有的資料庫資源以減少資源的浪費。本文使用了try with resources方式關閉資源,這是JDK7的語法糖,讀者可自行搜索。
完整代碼如下。
JDBC的最佳實踐
JDBC是如何實現Java程序和JDBC驅動的松耦合?
JDBC API使用Java的反射機制來實現Java程序和JDBC驅動的松耦合。看一下上文的JDBC示例,你會發現所有操作都是通過JDBC介面完成的,而驅動只有在通過Class.forName反射機制來載入的時候才會出現。
這是Java核心庫里反射機制的最佳實踐之一,它使得應用程序和驅動程序之間進行了隔離,讓遷移資料庫的工作變得更簡單。
Statement和PreparedStatement區別
預編譯
創建時的區別:
執行時的區別:
由上可以看出,PreparedStatement有預編譯的過程,已經綁定sql,之後無論執行多少次,都不會再去進行編譯,而Statement 不同,如果執行多次,則相應的就要編譯多少次sql,所以從這點看,PreparedStatement的效率會比Statement要高一些。PreparedStatement是預編譯的,所以可以有效的防止SQL注入等問題
佔位符
PrepareStatement可以替換變數在SQL語句中可以包含?,可以用?替換成變數。
而Statement只能用字元串拼接。
JDBC的ResultSet
在查詢資料庫後會返回一個ResultSet,它就像是查詢結果集的一張數據表。
ResultSet對象維護了一個游標,指向當前的數據行。開始的時候這個游標指向的是第一行。如果調用了ResultSet的next()方法游標會下移一行,如果沒有更多的數據了,next()方法會返回false。可以在for循環中用它來遍歷數據集。
默認的ResultSet是不能更新的,游標也只能往下移。也就是說你只能從第一行到最後一行遍歷一遍。不過也可以創建可以回滾或者可更新的ResultSet,像下面這樣。
當生成ResultSet的Statement對象要關閉或者重新執行或是獲取下一個ResultSet的時候,ResultSet對象也會自動關閉。
可以通過ResultSet的getter方法,傳入列名或者從1開始的序號來獲取列數據。
ResultSet的不同類型
根據創建Statement時輸入參數的不同,會對應不同類型的ResultSet。如果你看下Connection的方法,你會發現createStatement和prepareStatement方法重載了,以支持不同的ResultSet和並發類型。
ResultSet對象有三種類型。
ResultSet有兩種並發類型。