第八章 數據庫安全保護_第1頁
第八章 數據庫安全保護_第2頁
第八章 數據庫安全保護_第3頁
第八章 數據庫安全保護_第4頁
第八章 數據庫安全保護_第5頁
已閱讀5頁,還剩121頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第7章數據庫的安全保護本章要點

DBMS對數據庫的安全保護功能是通過四方面來實現的,即安全性控制、完整性控制、并發性控制和數據庫恢復。本章就將從這四方面來介紹數據庫的安全保護功能,重點要求讀者掌握它們的含義及實現這些安全保護功能的方法,可結合SQLServer加深四部分內容的理解與操作技能。本章邏輯結構7.1數據庫的安全性

7.1.1.數據庫安全性概述

7.1.2.

安全性控制的一般方法

7.1.3.

安全性控制的其它方法

7.1.4.

SQLServer安全性概述

7.2完整性控制

7.2.1.數據庫完整性概述

7.2.2.完整性規則的組成

7.2.3.完整性約束條件的分類

7.2.4.SQLServer完整性概述7.3并發控制與封鎖本章邏輯結構

7.3.1.數據庫并發性概述

7.3.2.事務的基本概念

7.3.3.并發操作與數據的不一致性

7.3.4.封鎖及其產生問題的解決

7.3.5.SQLServer的并發控制機制7.4數據庫的恢復

7.4.1.數據庫恢復概述

7.4.2.數據庫恢復的基本原理及其實現技術

7.4.3.數據庫的故障及其恢復策略

7.4.4.SQLServer的備份和還原機制

作業前言:數據庫安全的概念數據庫簡介信息與數據數據庫系統一般由4個部分組成:(1)數據庫,即存儲在磁帶、磁盤、光盤或其他外存介質上、按一定結構組織在一起的相關數據的集合。(2)數據庫管理系統(DBMS)。它是一組能完成描述、管理、維護數據庫的程序系統。它按照一種公用的和可控制的方法完成插入新數據、修改和檢索原有數據的操作。(3)數據庫管理員(DBA)。(4)用戶和應用程序。4數據庫的構成記錄;屬性二維表數據模型層次網狀關系數據庫操縱56問題的提出數據庫的一大特點是數據可以共享數據共享必然帶來數據庫的安全性問題數據庫系統中的數據共享不能是無條件的共享例:軍事秘密、國家機密、新產品實驗數據、市場需求分析、市場營銷策略、銷售計劃、客戶檔案、醫療檔案、銀行儲蓄數據數據庫安全性數據庫的安全性是指保護數據庫,以防止非法使用所造成數據的泄露、更改或破壞。安全性問題有許多方面,其中包括:(1)法律、社會和倫理方面,例如請求查詢信息的人是不有合法的權力。(2)物理控制方面,例如計算機機房或終端是否應該加鎖或用其他方法加以保護。(3)政策方面,確定存取原則,允許哪些用戶存取哪些數據。(4)運行方面,使用口令時,如何使口令保持秘密。(5)硬件控制方面,CPU是否提供任何安全性方面的功能,諸如存儲保護鍵或特權工作方式。(6)操作系統安全性方面,在主存儲器和數據文件用過以后,操作系統是否把它們的內容清除掉。(7)數據庫系統本身安全性方面。這里討論的是數據庫本身的安全性問題,即探討數據庫自身安全保護的策略與技術。

例如,甲用戶可以訪問表T1,但無權訪問表T2,如果乙用戶把表T2的所有記錄添加到表T1中之后,則由于乙用戶的操作,使甲用戶獲得了對表T2中記錄的訪問。 此外,用戶可以多次利用允許的訪問結果,經過邏輯推理得到他無權訪問的數據。7.1數據庫安全性7.1.1.數據庫安全性概述7.1.2.

安全性控制的一般方法7.1.3.

安全性控制的其它方法7.1.4.

SQLServer安全性概述返回本章首頁7.1.1數據庫安全性概述

數據庫的安全性是指保護數據庫,以防止非法使用所造成數據的泄露、更改或破壞。安全性問題有許多方面,其中包括:(1)法律、社會和倫理方面,例如請求查詢信息的人是不有合法的權力;(2)物理控制方面,例如計算機機房或終端是否應該加鎖或用其他方法加以保護;(3)政策方面,確定存取原則,允許哪些用戶存取哪些數據;(4)運行與技術方面,使用口令時,如何使口令保持秘密;BACK5.1.1數據庫安全性概述(5)硬件控制方面,CPU是否提供任何安全性方面的功能,諸如存儲保護鍵或特權工作方式;(6)操作系統安全性方面,在主存儲器和數據文件用過以后,操作系統是否把它們的內容清除掉;(7)數據庫系統本身安全性方面。BACK7.1.2安全性控制的一般方法

安全性控制是指要盡可能地杜絕所有可能的數據庫非法訪問。用戶非法使用數據庫可以有很多種情況。例如,編寫合法的程序繞過DBMS授權機制,通過操作系統直接存取、修改或備份有關數據。用戶訪問非法數據,無論它們是有意的還是無意的,都應該加以嚴格控制,因此,系統還要考慮數據信息的流動問題并加以控制,否則有潛在的危險性。因為數據的流動可能使無權訪問的用戶獲得訪問權利。為防止這一點,訪問的許可權還要結合過去訪問的情況而定。可見安全性的實施是要花費一定代價,并需縝密考慮的。安全保護策略就是要以最小的代價來最大程度防止對數據的非法訪問,通常需要層層設置安全措施。實際上,數據庫系統的安全性問題,類似于整個計算機系統一級級層層設置安全的情況,其安全控制模型一般如圖5.1所示。7.1.2安全性控制的一般方法BACK7.1.2安全性控制的一般方法

根據圖的安全模型,當用戶進入計算機系統時,系統首先根據輸入的用戶標識進行身份的鑒定,只有合法的用戶才準許進入系統。對已進入系統的用戶,DBMS還要進行存取控制,只允許用戶進行合法的操作BACKDBMS是建立在操作系統之上的,安全的操作系統是數據庫安全的前提。操作系統應能保證數據庫中的數據必須由DBMS訪問,而不允許用戶越過DBMS,直接通過操作系統或其它方式訪問。數據最后可以通過密碼的形式存儲到數據庫中。能做到非法者即使得到了加密數據,也無法識別它的安全效果。下面,本書就同數據庫有關的用戶標識和鑒定、存取控制、定義視圖、數據加密和審計等幾類安全性措施作一討論。7.1.2安全性控制的一般方法BACK1、用戶標識和鑒別用戶標識和鑒定是系統提供的最外層的安全保護措施,其方法是由系統提供一定的方式讓用戶標識自己的名字或身份,系統內部記錄著所有合法用戶的標識,每次用戶要求進入系統時,由系統進行核實,通過鑒定后才提供機器的使用權。用戶標識和鑒定的方法有:(1)單用戶名鑒別法:用一個用戶名或用戶標識符來標明用戶的身份,系統以此來鑒別用戶的合法性.7.1.2安全性控制的一般方法BACK7.1.2安全性控制的一般方法(2)用戶名與口令聯合鑒別法:用戶標識符是用戶公開的標識,它不足以成為鑒別用戶身份的憑證。(3)透明公式鑒別法:每個用戶都預先約定好一個過程或者函數,鑒別用戶身份時,系統提供一個隨機數,用戶根據自己預先約定的計算過程或者函數進行計算,系統根據計算結果辨別用戶身份的合法性。BACK7.1.2安全性控制的一般方法2、用戶存取權限控制用戶存取權限指的是不同的用戶對于不同的數據對象允許執行的操作權限。存取權限由兩個要素組成,數據對象和操作類型。定義一個用戶的存取權限就是要定義這個用戶可以在哪些數據對象上進行哪些類型的操作。在數據庫系統中,定義用戶存取權限稱為授權。授權有兩種:(1)系統權限:由DBA授予某些數據庫用戶,只有得到系統權限,才能成為數據庫用戶。BACK7.1.2安全性控制的一般方法(2)對象權限:可以由DBA授予,也可以由數據對象的創建者授予,使數據庫用戶具有對某些數據對象進行某些操作的權限.這些授權定義經過編譯后以一張授權表的形式存放在數據字典中。授權表主要有三個屬性,用戶標識、數據對象和操作類型。BACK7.1.2安全性控制的一般方法3、視圖機制為不同的用戶定義不同的視圖,可以限制各個用戶的訪問范圍。通過視圖機制把要保密的數據對無權存取這些數據的用戶隱藏起來,從而自動地對數據提供一定程度的安全保護。4、數據加密數據加密是防止數據庫中數據在存儲和傳輸中失密的有效手段.加密的基本思想是根據一定的算法將原始數據加密成為不可直接識別的格式,數據以密碼的形式存儲和傳輸.BACK7.1.2安全性控制的一般方法加密方法有兩種:(1)替換方法:該方法使用密鑰將明文中的每一個字符轉換為密文中的一個字符.(2)轉換方法:該方法將明文中的字符按不同的順序重新排列.用密碼存儲數據,在存入時需加密,在查詢時需解密,這個過程會占用較多的系統資源,降低了數據庫的性能。5、審計實際上任何系統的安全性措施都不是絕對可靠的,竊密者總有辦法打破這些控制。審計功能是一種監視措施,跟蹤記錄有關數據的訪問活動。BACK7.1.3安全性控制的其它方法

1、強制存取控制(MAC)有些數據庫系統的數據要求很高的保密性,通常具有靜態的嚴格的分層結構,強制存取控制能實現這種高保密性要求.這種方法的基本思想在于每個數據對象(文件、記錄記錄或宇段等)賦予一定的密級,級別從高到低有:絕密級、機密級、秘密級和公用級.每個用戶也具有相應的級別,稱為許可證級別.在系統運行時,采用如下兩條簡單規則:(1)用戶U只能查看比它級別低或同級的數據。(2)用戶U只能修改和它同級的數據.強制存取控制是一種獨立于值的控制方法.它的優點是系統能執行“信息流控制”。BACK5.1.3安全性控制的其它方法

1、強制存取控制(MAC)

在第②條,用戶U顯然不能修改比它級別高的數據,也不能修改比它級別低的數據,這樣主要是為了防止具有較高級別的用戶將該級別的數據復制到較低級別的文件中。強制存取控制是一種獨立于值的控制方法。它的優點是系統能執行“信息流控制”。在前面介紹的授權方法中,允許凡有權查看保密數據的用戶就可以把這種數據拷貝到非保密的文件中,造成無權用戶也可接觸保密數據。而強制存取控制可以避免這種非法的信息流動。注意:這種方法在通用數據庫系統中應用不廣泛,只是在某些專用系統中才有用。BACK7.1.3安全性控制的其它方法

2、統計數據庫的安全性查詢僅僅是某些記錄的統計值,例如求記錄數、和、平均值等。在統計數據庫中,雖然不允許用戶查詢單個記錄的信息,但是用戶可以通過處理足夠多的匯總信息來分析出單個記錄的信息.在統計數據庫中,對查詢應作下列限制:①一個查詢查到的記錄個數至少是n;②兩個查詢查到的記錄的“交”數目至多是m.

BACK7.1.3安全性控制的其它方法

2、統計數據庫的安全性

系統可以調整n和m的值,使得用戶很難在統計數據庫中獲取其他個別記錄的信息,但要做到完全杜絕是不可能的。我們應限制用戶計算和、個數、平均值的能力。如果一個破壞者只知道他自己的數據,那么已經證明,他至少要花1+(n-2)/m次查詢才有可能獲取其他個別記錄的信息。因而,系統應限制用戶查詢的次數在1+(n-2)/m次以內。但是這個方法還不能防止兩個破壞者聯手查詢導致數據的泄露。

BACK7.1.3安全性控制的其它方法

2、統計數據庫的安全性

保證數據庫安全性的另一個方法是“數據污染”,也就是在回答查詢時,提供一些偏離正確值的數據,以免數據泄露。當然,這個偏離要在不破壞統計數據的前提下進行。此時,系統應該在準確性和安全性之間作出權衡。當安全性遭到威脅時,只能降低準確性的標準。BACK7.1.4SQLServer安全性概述SQLServer安全系統的構架建立在用戶和用戶組的基礎上.SQLServer提供了3種安全管理模式,即標準模式、集成模式和混合模式,數據庫設計者和數據庫管理員可以根據實際情況進行選擇。1、兩個安全性階段:身份驗證和授權。2、用戶權限:登錄創建在Windows中,而非SQLServer中。BACK7.1.4SQL

Server安全性概述當用戶連接到SQLServer實例后,他們可以執行的活動由授予以下帳戶的權限確定:(1)用戶的安全帳戶;(2)用戶的安全帳戶所屬Windows組或角色層次結;(3)用戶若要進行任何涉及更改數據庫定義或訪問數據的活動,則必須有相應的權限。BACK7.1.4

SQLServer安全性概述

3、視圖安全機制SQLServer通過限制可由用戶使用的數據,可以將視圖作為安全機制。用戶可以訪問某些數據,進行查詢和修改,但是表或數據庫的其余部分是不可見的,也不能進行訪問。4、加密方法SQLServer支持加密或可以加密的內容為:①SQLServer中存儲的登錄和應用程序角色密碼;②作為網絡數據包而在客戶端和服務器端之間發送的數據;③SQLServer中如下對象的定義內容:存儲過程、用戶定義函數、視圖、觸發器、默認值、規則等。BACK7.1.4SQLServer安全性概述5、審核活動SQLServer提供審核功能,用以跟蹤和記錄每個SQLServer實例上已發生的活動(如成功和失敗的記錄)。SQLServer還提供管理審核記錄的接口,即SQL事件探查器。只有sysadmin固定安全角色的成員才能啟用或修改審核,而且審核的每次修改都是可審核的事件。BACK7.2數據庫完整性

5.2.1數據庫完整性概述5.2.2完整性規則的組成5.2.3完整性約束條件的分類5.2.4SQLServer完整性概述7.2.1數據庫完整性概述

數據庫的完整性是指保護數據庫中數據的正確性、有效性和相容性,防止錯誤的數據進入數據庫造成無效操作。顯然,維護數據庫的完整性非常重要,數據庫中的數據是否具備完整性關系到數據能否真實地反映現實世界。數據庫的完整性和安全性是數據庫保護的兩個不同的方面。安全性是保護數據庫,以防止非法使用所造成數據的泄露、更改或破壞,安全性措施的防范對象是非法用戶和非法操作;完整性是防止合法用戶使用數據庫時向數據庫中加入不符合語義的數據,完整性措施的防范對象是不合語義的數據。BACK7.2.2完整性規則的組成

完整性規則主要由以下三部分構成:(1)觸發條件:規定系統什么時候使用規則檢查數據;(2)約束條件:規定系統檢查用戶發出的操作請求違背了什么樣的完整性約束條件;(3)違約響應:規定系統如果發現用戶的操作請求違背了完整性約束條件,應該采取一定的動作來保證數據的完整性,即違約時要做的事情。完整性規則從執行時間上可分為立即執行約束(ImmediateConstraints)和延遲執行約束(DeferredConstraints)。立即執行約束是指在執行用戶事務過程中,某一條語句執行完成后,系統立即對此數據進行完整性約束條件檢查;延遲執行約束是指在整個事務執行結束后,再對約束條件進行完整性檢查,結果正確后才能提交。BACK7.2.2完整性規則的組成一條完整性規則可以用一個五元組(D,O,A,C,P)來形式化地表示。其中:D(data):代表約束作用的數據對象;O(operation):代表觸發完整性檢查的數據庫操作,即當用戶發出什么操作請求時需要檢查該完整性規則;A(assertion):代表數據對象必須滿足的語義約束,這是規則的主體;C(condition):代表選擇A作用的數據對象值的謂詞;P(procedure):代表違反完整性規則時觸發執行的操作過程。BACK7.2.2完整性規則的組成例如,對于“學號不能為空”的這條完整性約束,D:代表約束作用的數據對象為SNO屬性;O(operation):當用戶插入或修改數據時需要檢查該完整性規則;A(assertion):SNO不能為空;C(condition):A可作用于所有記錄的SNO屬性;P(procedure):拒絕執行用戶請求。BACK7.2.3完整性約束條件的分類在數據庫領域中,有四種最常用的數據模型,它們是:被稱為非關系模型的層次模型、網狀模型、關系模型和面向對象模型。本章簡要介紹層次模型、網狀模型、關系模型。層次模型是數據庫系統中最早出現的數據模型,它用樹形結構表示各類實體以及實體間的聯系。層次模型數據庫系統的典型代表是IBM公司的IMS(InformationManagementSystems)數據庫管理系統,這是一個曾經廣泛使用的數據庫管理系統。現實世界中有一些的實體之間的聯系本來就呈現出一種很自然的層次關系,如家庭關系,行政關系。BACK7.2.3完整性約束條件的分類

1、值的約束和結構的約束從約束條件使用的對象來分,可把約束分為值的約束和結構的約束。值的約束:即對數據類型、數據格式、取值范圍等進行規定。(1)對數據類型的約束,包括數據的類型、長度、單位和精度等。例如,規定學生性別的數據類型應為字符型,長度為2。(2)對數據格式的約束。例如,規定出生日期的數據格式為YYYY.MM.DD。(3)對取值范圍的約束。例如,月份的取值范圍為1~12,日期1~31。BACK7.2.3完整性約束條件的分類(4)對空值的約束。空值表示未定義或未知的值,它與零值和空格不同。有的列值允許空值,有的則不允許。例如,學號和課程號不可以為空值,但成績可以為空值。結構約束:即對數據之間聯系的約束。數據庫中同一關系的不同屬性之間,應滿足一定的約束條件,同時,不同關系的屬性之間也有聯系,也應滿足一定的約束條件。BACK7.2.3完整性約束條件的分類常見的結構約束有如下四種:(1)函數依賴約束:說明了同一關系中不同屬性之間應滿足的約束條件。如:2NF,3NF,BCNF這些不同的范式應滿足不同的約束條件。大部分函數依賴約束都是隱含在關系模式結構中的,特別是對于規范化程度較高的關系模式,都是由模式來保持函數依賴的。(2)實體完整性約束:說明了關系主鍵(或主碼)的屬性列必須唯一,其值不能為全空或部分為空。(3)參照完整性約束:說明了不同關系的屬性之間的約束條件,即外部鍵(外碼)的值應能夠在被參照關系的主鍵值中找到或取空值。BACK7.2.3完整性約束條件的分類(4)用戶自定義完整性:從實際應用系統出發,按需定義屬性之間要滿足的約束條件。(5)統計約束,規定某個屬性值與關系多個元組的統計值之間必須滿足某種約束條件。例如,規定系主任的獎金不得高于該系的平均獎金的50%,不得低于該系的平均獎金的15%。這里該系平均獎金的值就是一個統計計算值。其中,實體完整性約束和參照完整性約束是關系模型的兩個極其重要的約束,被稱為關系的兩個不變性。而統計約束實現起來開銷很大。BACK7.2.3完整性約束條件的分類2、靜態約束和動態約束完整性約束從約束對象的狀態可分為靜態約束和動態約束。靜態約束靜態約束是指在數據庫每一個確定狀態時的數據對象所應滿足的約束條件,它是反映數據庫狀態合理性的約束,這是最重要的一類完整性約束。上面介紹的值的約束和結構的約束均屬于靜態約束。動態約束動態約束是指數據庫從一種狀態轉變為另一種狀態時(數據庫數據變動前后),新、舊值之間所應滿足的約束條件,它是反映數據庫狀態變遷的約束。例如,學生年齡在更改時只能增長,職工工資在調整時不得低于其原來的工資。BACK7.2.4SQLServer完整性概述

SQLServer中數據完整性可分為四種類型:實體完整性、域完整性、引用完整性、用戶定義完整性。另外,觸發器、存儲過程等也能以一定方式控制數據完整性。1、實體完整性實體完整性將行定義為特定表的唯一實體。SQLServer支持如下實體完整性相關的約束:(1)PRIMARYKEY約束:在一個表中不能有兩行包含相同的主鍵值,不能在主鍵內的任何列中輸入NULL值。(2)UNIQUE約束:UNIQUE約束在列集內強制執行值的唯一性,對于UNIQUE約束中的列,表中不允許有兩行包含相同的非空值。BACK7.2.4SQLServer完整性概述(3)IDENTITY屬性:IDENTITY屬性能自動產生唯一標識值,指定為IDENTITY的列一般作為主鍵。2、域完整性:是指給定列的輸入正確性與有效性。SQLServer中強制域有效性的方法有:限制類型,如通過數據類型、用戶自定義數據類型等實現;格式限制,如通過CHECK約束和規則等實現;列值的范圍限定,如通過PRIMARYKEY約束、UNIQUE約束、FOREIGNKEY約束、CHECK約束、DEFAULT定義、NOTNULL定義等實現。BACK7.2.4SQLServer完整性概述3、引用完整性(即參照完整性)SQLServer引用完整性主要由FOREIGNKEY約束體現,它標識表之間的關系,一個表的外鍵指向另一個表的候選鍵或唯一鍵。強制引用完整性時,SQLServer禁止用戶進行下列操作:(1)當主表中沒有關聯的記錄時,將記錄添加到相關表中。(2)更改主表中的值并導致相關表中的記錄孤立。BACK7.2.4SQLServer完整性概述(3)從主表中刪除記錄,但仍存在與該記錄匹配的相關記錄。在DELETE或UPDATE所產生的所有級聯引用操作的諸表中,每個表只能出現一次。多個級聯操作中只要有一個表因完整性原因操作失敗,整個操縱將失敗而回滾。4、用戶定義完整性SQLServer用戶定義完整性主要由Check約束所定義的列級或表級約束體現,用戶定義完整性還能由規則、觸發器、客戶端或服務器端應用程序靈活定義。BACK7.2.4SQLServer完整性概述5、觸發器SQLServer2000觸發器是一類特殊的存儲過程,被定義為在對表或視圖發出UPDATE、INSERT或DELETE語句時自動執行。觸發器可以擴展SQLServer約束、默認值和規則的完整性檢查邏輯,一個表可以有多個觸發器。6、其它機制SQLServer2000支持存儲過程中制定約束規則,SQLServer2000的并發控制機制能保障多用戶存取數據時的完整性。BACK7.3數據庫并發性

5.3.1數據庫并發性概述5.3.2事務的基本概念5.3.3并發操作與數據的不一致性5.3.4封鎖及其產生問題的解決5.3.5SQLServer的并發控制機制返回本章首頁7.3.1數據庫并發性概述

每個用戶在存取數據庫中的數據時,可能是串行執行,即每個時刻只有一個用戶程序運行,也可能是多個用戶并行地存取數據庫。數據庫的最大特點之一就是數據資源是共享的,串行執行意味著一個用戶在運行程序時,其他用戶程序必須等到這個用戶程序結束才能對數據庫進行存取,這樣數據庫系統的利用率會極低。數據庫并發執行是主流。數據庫的并發控制機制能解決這類問題,以保持數據庫中數據的在多用戶并發操作時的一致性、正確性。BACK7.3.2事務的基本概念

1、事務(Transaction)的定義

事務是數據庫系統中執行的一個工作單位,它是由用戶定義的一組操作序列組成。一個事務可以是一組SQL語句、一條SQL語句或整個程序,一個應用程序可以包括多個事務。事務的開始與結束可以由用戶顯式控制。如果用戶沒有顯式地定義事務,則由DBMS按照缺省規定自動劃分事務。BACK7.3.2事務的基本概念在SQL語言中,定義事務的語句有三條:(1)BEGINTRANSACTION表示事務的開始;(控制事務)(2)COMMIT表示事務的提交,即將事務中所有對數據庫的更新寫回到磁盤上的物理數據庫中去,此時事務正常結束;(3)ROLLBACK表示事務的回滾,即在事務運行的過程中發生了某種故障,事務不能繼續執行,系統將事務中對數據庫的所有已完成的更新操作全部撤銷,再回滾到事務開始時的狀態。BACK7.3.2事務的基本概念2、事務的特征事務是由有限的數據庫操作序列組成,但并不是任意的數據庫操作序列都能成為事務,為了保護數據的完整性,一般要求事務具有以下四個特征:(1)原子性(Atomic):一個事務是一個不可分割的工作單位,事務在執行時,應該遵守“要么不做,要么全做”(nothingorall)的原則,即不允許事務部分的完成。即使因為故障而使事務未能完成,它執行的部分操作要被取消。(2)一致性(Consistency):事務對數據庫的操作使數據庫從一個一致狀態轉變到另一個一致狀態。所謂數據庫的一致狀態是指事務操作后數據庫中的數據要滿足各種完整性約束要求。BACK7.3.2事務的基本概念例如,銀行企業中,“從帳號A轉移資金額M到帳號B”是一個典型的事務,這個事務包括兩個操作,從帳號A中減去資金額M和在帳號B中增加資金額M,如果只執行其中一個操作,則數據庫處于不一致狀態,帳務會出現問題。也就是說,兩個操作要么全做,要么全不做,否則就不能成為事務。可見事務的一致性與原子性是密切相關的。3、隔離性(Isolation):如果多個事務并發地執行,應像各個事務獨立執行一樣,一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對并發的其他事務是隔離的。并發控制就是為了保證事務間的隔離性。BACK7.3.2事務的基本概念4、持久性(Durability):指一個事務一旦提交,它對數據庫中數據的改變就應該是持久的,即使數據庫因故障而受到破壞,DBMS也應該能夠恢復。事務上述四個性質的英文術語的第一個字母分別為A、C、I、D。因此,這四個性質也稱為事務的ACID準則。BACK7.3.2事務的基本概念BEGINTRANSACTIONREADAA←A-MIFA<0/*A款不足*/THENBEGINDISPLAY“A款不足”ROLLBACKENDELSE/*撥款*/BEGINB←B+MDISPLAY“撥款完成”COMMITEND下面是一個事務的例子,從帳號A轉移資金額R到帳號B:BACK7.3.2事務的基本概念這是對一個簡單事務的完整的描述。該事務有兩個出口:當A帳號的款項不足時,事務以ROLLBACK(撤銷)命令結束,即撤銷該事務的影響;另一個出口是以COMMIT(提交)命令結束,完成從帳號A到帳號B的撥款。在COMMIT之前,即在數據庫修改過程中,數據可能是不一致的,事務本身也可能被撤銷。只有在COMMIT之后,事務對數據庫所產生的變化才對其他事務開放,這就可以避免其他事務訪問不一致或不存在的數據。BACK7.3.3并發操作與數據的不一致性

當同一數據庫系統中有多個事務并發運行時,如果不加以適當控制,可能產生數據的不一致性。[例1]并發取款操作。假設存款余額R=1000元,甲事務T1取走存款200元,乙事務T2取走存款300元,如果正常操作,即甲事務T1執行完畢再執行乙事務T2,存款余額更新后應該是500元。但是如果按照如下順序操作,則會有不同的結果:甲事務T1讀取存款余額R=1000元;乙事務T2讀取存款余額R=1000元;BACK7.3.3并發操作與數據的不一致性

甲事務T1取走存款200元,修改存款余額R=R-200=800,把R=800寫回到數據庫;乙事務T2取走存款300元,修改存款余額R=R-300=700,把R=700寫回到數據庫。結果兩個事務共取走存款500元,而數據庫中的存款卻只少了300元。得到這種錯誤的結果是由甲、乙兩個事務并發操作引起的。BACK7.3.3并發操作與數據的不一致性數據庫的并發操作導致的數據庫不一致性主要有以下三種:1、丟失更新(LostUpdate)當兩個事務T1和T2讀入同一數據做修改,并發執行時,T2把T1或T1把T2的修改結果覆蓋掉,造成了數據的丟失更新問題,導致數據的不一致。仍以[例1]中的操作為例進行分析。在表5.5中,數據庫中R的初值是1000,事務T1包含三個操作:讀入R初值(FINDR);計算(R=R-200);更新R(UPDATER)。BACK7.3.3并發操作與數據的不一致性'表5.5丟失更新問題時間事務T1R的值事務T2t0

1000

t1FINDR

t2

FINDRt3R=R-200

t4

R=R-300t5UPDATER

t6

800UPDATERt7

700

事務T2也包含三個操作:FINDR;計算(R=R-300);UPDATER。如果事務T1和T2順序執行,則更新后,R的值是500。但如果T1和T2按照表5.5所示的并發執行,R的值是700,得到錯誤的結果,原因在于在t7時刻丟失了T1對數據庫的更新操作。因此,這個并發操作不正確。BACK7.3.3并發操作與數據的不一致性2、污讀(DirtyRead)事務T1更新了數據R,事務T2讀取了更新后的數據R,事務T1由于某種原因被撤消,修改無效,數據R恢復原值。事務T2得到的數據與數據庫的內容不一致,這種情況稱為“污讀”(又名臟讀)。BACK7.3.3并發操作與數據的不一致性在表5.6中,事務T1把R的值改為900,但此時尚未做COMMIT操作,事務T2將修改過的值800讀出來,之后事務T1執行ROLLBACK操作,R的值恢復為1000,而事務T2將仍在使用已被撤消了的R值800。時間事務T1R的值事務T2t0

1000

t1FINDR

t2R=R-200

t3UPDATER

t4

800FINDRt5ROLLBACK

t6

1000

表5.6污讀問題

BACK7.3.3并發操作與數據的不一致性原因在于在t4時刻事務T2讀取了T1未提交的更新操作結果,這種值是不穩定的,在事務T1結束前隨時可能執行ROLLBACK操作。對于這些未提交的隨后又被撤消的更新數據稱為“臟數據”。比如,這里事務T2在t2時刻讀取的就是“臟數據”。3、不可重讀(UnrepeatableRead)事務T1讀取了數據R,事務T2讀取并更新了數據R,當事務T1再讀取數據R以進行核對時,得到的兩次讀取值不一致,這種情況稱為“不可重讀”。BACK7.3.3并發操作與數據的不一致性在表5.7中,在t0時刻事務T1讀取R的值為1000,但事務T2在t4時刻將R的值更新為為700。所以T1在t5時刻所讀取R的值700已經與開始讀取的值1000不一致了。時間事務T1R的值事務T2t0

1000

t1FINDR1000

t2

FINDRt3

R=R-300t4

700UPDATERt5FINDR700

表5.7不可重讀

BACK7.3.3并發操作與數據的不一致性產生上述三類數據不一致性的主要原因就是并發操作破壞了事務的隔離性。并發控制就是要求DBMS提供并發控制功能以正確的方式高度并發事務,避免并發事務之間的相互干擾造成數據的不一致性,保證數據庫的完整性。BACK7.3.4封鎖及其產生問題的解決

實現并發控制的方法主要有兩種:封鎖(Lock)技術和時標(Timestamping)技術(時標意指一種將時間分配到事件的制度)。這里只介紹封鎖技術。1、封鎖類型(LockType)

所謂封鎖就是當一個事務在對某個數據對象(可以是數據項、記錄、數據集、以至整個數據庫)進行操作之前,必須獲得相應的鎖,以保證數據操作的正確性和一致性。封鎖是目前DBMS普遍采用的并發控制方法,基本的封鎖類型有兩種:排它鎖和共享鎖。BACK7.3.4封鎖及其產生問題的解決(1)排它鎖(ExclusiveLock)排它鎖又稱寫鎖,簡稱為X鎖,其采用的原理是禁止并發操作。當事務T對某個數據對象R實現X封鎖后,其他事務要等T解除X封鎖以后,才能對R進行封鎖。這就保證了其他事務在T釋放R上的鎖之前,不能再對R進行操作。(2)共享鎖(ShareLock)共享鎖又稱讀鎖,,簡稱為S鎖,其采用的原理是允許其他用戶對同一數據對象進行查詢,但不能對該數據對象進行修改。當事務T對某個數據對象R實現S封鎖后,其他事務只能對R加S鎖,而不能加X鎖,直到T釋放R上的S鎖。這就保證了其他事務在T釋放R上的S鎖之前,只能讀取R,而不能再對R作任何修改。BACK7.3.4封鎖及其產生問題的解決2、封鎖協議(LockProtocol)封鎖可以保證合理的進行并發控制,保證數據的一致性。實際上,鎖是一個控制塊,其中包括被加鎖記錄的標識符及持有鎖的事務的標識符等。在封鎖時,要考慮一定的封鎖規則,例如,何時開始封鎖、封鎖多長時間、何時釋放等,這些封鎖規則稱為封鎖協議。對封鎖方式規定不同的規則,就形成了各種不同的封鎖協議。封鎖協議在不同程序上對正確控制并發操作提供了一定的保證。BACK7.3.4封鎖及其產生問題的解決

上面講述過的并發操作所帶來的丟失更新、污讀和不可重讀等數據不一致性問題,可以通過三級封鎖協議在不同程度上給予解決,下面介紹三級封鎖協議。1、一級封鎖協議一級封鎖協議的內容是:事務T在修改數據對象之前必須對其加X鎖,直到事務結束。具體地說,就是任何企圖更新記錄R的事務必須先執行“XLOCKR”操作,以獲得對該記錄進行更新的能力并對它取得X封鎖。如果未獲準“X封鎖”,那么這個事務進入等待狀態,一直到獲準“X封鎖”,該事務才繼續做下去。該事務規定事務在更新記錄R時必須獲得排它性封鎖,使得兩個同時要求更新R的并行事務之一必須在一個事務更新操作執行完成之后才能獲得X封鎖,這樣就避免了兩個事務讀到同一個R值而先后更新時所發生的丟失更新問題。BACK7.3.4封鎖及其產生問題的解決利用一級封鎖協議可以解決表5.5中的數據丟失更新問題,如表5.8所示。事務T1先對R進行X封鎖(XLOCK),事務T2執行“XLOCKR”操作,未獲準“X封鎖”,則進入等待狀態,直到事務T1更新R值以后,解除X封鎖操作(UNLOCKX)。此后事務T2再執行“XLOCKR”操作,獲準“X封鎖”,并對R值進行更新(此時R已是事務T1更新過的值,R=900)。這樣就能得出正確的結果。一級封鎖協議只有當修改數據時才進行加鎖,如果只是讀取數據并不加鎖,所以它不能防止“污讀”和“重讀”數據。BACK7.3.4封鎖及其產生問題的解決表5.8無丟失更新問題時間事務T1R的值事務T2t0XLOCKR1000

t1FINDR

t2

XLOCKRt3R=R-200

WAITt4UPDATER

WAITt5UNLOCKX800WAITt6

XLOCKRt7

R=R-300t8

UPDATERt9

500UNLOCKXBACK7.3.4封鎖及其產生問題的解決2、二級封鎖協議二級封鎖協議的內容是:在一級封鎖協議的基礎上,另外加上事務T在讀取數據R之前必須先對其加S鎖,讀完后釋放S鎖。所以二級封鎖協議不但可以解決更新時所發生的數據丟失問題,還可以進一步防止“污讀”。BACK7.3.4封鎖及其產生問題的解決利用二級封鎖協議可以解決表5.6中的數據“污讀”問題,如表5.9所示。表5.9

無污讀問題BACK時間事務T1R的值事務T2t0XLOCKR1000t1FINDRt2R=R-200t3UPDATERt4800SLOCKRt5ROLLBACKWAITt6UNLOCKR1000SLOCKRt71000FINDRt8UNLOCKS7.3.4封鎖及其產生問題的解決事務T1先對R進行X封鎖(XLOCK),把R的值改為800,但尚未提交。這時事務T2請求對數據R加S鎖,因為T1已對R加了X鎖,T2只能等待,直到事務T1釋放X鎖。之后事務T1因某種原因撤銷,數據R恢復原值1000,并釋放R上的X鎖。事務T2可對數據R加S鎖,讀取R=1000,得到了正確的結果,從而避免了事務T2讀取“臟數據”。BACK7.3.4封鎖及其產生問題的解決3、三級封鎖協議三級封鎖協議的內容是:在一級封鎖協議的基礎上,另外加上事務T在讀取數據R之前必須先對其加S鎖,讀完后并不釋放S鎖,而直到事務T結束才釋放。所以三級封鎖協議除了可以防止更新丟失問題和“污讀”數據外,還可進一步防止不可重讀數據,徹底解決了并發操作所帶來的三個不一致性問題。利用三級封鎖協議可以解決表5.7中的不可重讀問題。BACK7.3.4封鎖及其產生問題的解決3、封鎖粒度(LockGranularity)封鎖對象的大小稱為封鎖粒度。根據對數據的不同處理,封鎖的對象可以是這樣一些邏輯單元:字段、數據庫等,也可以是這樣一些物理單元:頁(數據頁或索引頁)、塊等。封鎖粒度與系統的并發度和并發控制的開銷密切相關。封鎖粒度越小,系統中能夠被封鎖的對象就越多,并發度越高,但封鎖機構復雜,系統開銷也就越大。封鎖粒度越大,系統中能夠被封鎖的對象就越少,并發度越小,封鎖機構簡單,相應系統開銷也就越小。因此,在實際應用中,選擇封鎖粒度時應同時考慮封鎖機制和并發度兩個因素,對系統開銷與并發度進行權衡,以求得最優的效果。BACK7.3.4封鎖及其產生問題的解決4、死鎖和活鎖封鎖技術可有效解決并行操作引起的數據不一致性問題,但也可產生新的問題,即可能產生活鎖和死鎖問題。1、活鎖(Livelock)當某個事務請求對某一數據的排它性封鎖時,由于其他事務一直優先得到對該數據的封鎖與操作而使這個事務一直處于等待狀態,這種狀態形成活鎖。例如,事務T1在對數據R封鎖后,事務T2又請求封鎖R,于是T2等待。T3也請求封鎖R。當T1釋放了R上的封鎖后,系統首先批準了T3的請求,T2繼續等待。然后又有T4請求封鎖R,T3釋放了R上的封鎖后,系統又批準了T4的請求…T2可能永遠處于等待狀態,從而發生了活鎖。如表5.11所示。BACK7.3.4封鎖及其產生問題的解決時間事務T1事務T2事務T3事務T4t0LOCKR

t1…LOCKR

t2…WAITLOCKR

t3UNLOCKWAITWAITLOCKRt4…WAITLOCKRWAITt5

WAIT

WAITt6

WAITUNLOCKWAITt7

WAIT

LOCKRt8

WAIT

時間事務T1事務T2t0LOCKR1

t1

LOCKR2t2

t3LOCKR2

t4WAIT

t5WAITLOCKR1t6WAITWAITt7WAITWAIT表5.11活鎖表5.12死鎖BACK7.3.4封鎖及其產生問題的解決2、死鎖(Deadlock)在同時處于等待狀態的兩個或多個事務中,每個事務都在等待其中另一個事務解除封鎖,它才能繼續執行下去,結果造成任何一個事務都無法繼續執行,這種狀態稱為死鎖。例如,事務T1在對數據R1封鎖后,又要求對數據R2封鎖,而事務T2已獲得對數據R2的封鎖,又要求對數據R1封鎖,這樣兩個事務由于都不能得到全部所需封鎖而處于等待狀態,發生了死鎖。如表5.12所示。BACK7.3.4封鎖及其產生問題的解決(1)死鎖產生的條件發生死鎖的必要條件有以下四條:①互斥條件:一個數據對象一次只能被一個事務所使用,即對數據的封鎖采用排它式;②不可搶占條件:一個數據對象只能被占有它的事務所釋放,而不能被別的事務強行搶占;③部分分配條件:一個事務已經封鎖分給它的數據對象,但仍然要求封鎖其他數據;④循環等待條件:允許等待其他事務釋放數據對象,系統處于加鎖請求相互等待的狀態。BACK7.3.4封鎖及其產生問題的解決(2)死鎖的預防死鎖一旦發生,系統效率將會大大下降,因而要盡量避免死鎖的發生。在操作系統的多道程序運行中,由于多個進程的并行執行需要分別占用不同資源時,也會發生死鎖。要想預防死鎖的產生,就得破壞形成死鎖的條件。同操作系統預防死鎖的方法類似,在數據庫環境下,常用的方法有以下兩種:①一次加鎖法BACK7.3.4封鎖及其產生問題的解決圖5.2一次加鎖法

一次加鎖法是每個事物必須將所有要使用的數據對象全部依次加鎖,并要求加鎖成功,只要一個加鎖不成功,表示本次加鎖失敗,則應該立即釋放所有已加鎖成功的數據對象,然后重新開始從頭加鎖。一次加鎖法的程序框圖如圖5.2。BACK7.3.4封鎖及其產生問題的解決一次加鎖法雖然可以有效地預防死鎖的發生,但也存在一些問題。首先,對某一事務所要使用的全部數據一次性加鎖,擴大了封鎖的范圍,從而降低了系統的并發度。其次,數據庫中的數據是不斷變化的,原來不要求封鎖的數據,在執行過程中可能會變成封鎖對象,所以很難事先精確地確定每個事務所要封鎖的數據對象,這樣只能在開始擴大封鎖范圍,將可能要封鎖的數據全部加鎖,這就進一步降低了并發度,影響了系統的運行效率。BACK7.3.4封鎖及其產生問題的解決②順序加鎖法順序加鎖法是預先對所有可加鎖的數據對象規定一個加鎖順序,每個事務都需要按此順序加鎖,在釋放時,按逆序進行。順序加鎖法同一次加鎖法一樣,也存在一些問題。因為事務的封鎖請求可以隨著事務的執行而動態地決定,所以很難事先確定封鎖對象,從而更難確定封鎖順序。即使確定了封鎖順序,隨著數據操作的不斷變化,維護這些數據的封鎖順序要需要很大的系統開銷。BACK7.3.4封鎖及其產生問題的解決在數據庫系統中,由于可加鎖的目標集合不但很大,而且是動態變化的;可加鎖的目標常常不是按名尋址,而是按內容尋址,預防死鎖常要付出很高的代價,因而上述兩種在操作系統中廣泛使用的預防死鎖的方法并不很適合數據庫的特點。在數據庫系統中,還有一種解決死鎖的辦法,即可以允許發生死鎖,但在死鎖發生后可以由系統及時自動診斷并解除已發生的死鎖,從而避免事務自身不可解決的資源爭用問題。BACK7.3.4封鎖及其產生問題的解決(3)死鎖的診斷與解除數據庫系統中診斷死鎖的方法與操作系統類似。可以利用事務信賴圖的形式來測試系統中是否存在死鎖。例如在圖5.3中,事務T1需要數據R1,但R1已經被事務T2封鎖,那么從T1到T2劃一個箭頭。如果在事務依賴圖中沿著箭頭方向存在一個循環,那么死鎖的條件就形成了,系統就會出現死鎖。圖5.3事務依賴圖BACK7.3.4封鎖及其產生問題的解決如果已經發現死鎖,DBA從依賴相同資源的事務中抽出某個事務作為犧牲品,將它撤銷,并釋放此事務占用的所有數據資源,分配給其他事務,使其他事務得以繼續運行下去,這樣就有可能消除死鎖。在解除死鎖的過程中,抽取犧牲事務的標準是根據系統狀態及其應用的實際情況來確定的,通常采用的方法之一是選擇一個處理死鎖代價最小的事務,將其撤銷;或從用戶等級角度考慮,取消等級低的用戶事務,釋放其封鎖的資源給其它需要的事務。BACK7.3.5SQLServer的并發控制機制

SQLServer使用加鎖技術確保事務完整性和數據庫一致性。鎖定可以防止用戶讀取正在由其他用戶更改的數據,并可以防止多個用戶同時更改相同數據。雖然SQLServer自動強制鎖定,但可以通過了解鎖定并在應用程序中自定義鎖定來設計更有效的并發控制應用程序。SQLServer提供如下八種鎖類型:共享(S)、更新(U)、排它(X)、意向共享(IS)、意向排它(IX)、與意向排它共享(SIX)、架構(Sch)、大容量更新(BU),只有兼容的鎖類型才可以放置在已鎖定的資源上。BACK7.3.5SQLServer的并發控制機制SQLServer使用的主要鎖類型描述如下:①共享(S):用于不更改或不更新數據的操作(只讀操作如select語句)。資源上存在共享鎖時,任何其它事務都不能修改數據;②更新(U):用于可更新的資源中。一次只有一個事務可以獲得資源的更新鎖。如果事務修改資源,則更新鎖轉換為排它(X)鎖。否則鎖轉換為共享鎖。防止當多個會話在讀取、鎖定以及隨后可能進行的資源更新時發生死鎖;BACK7.3.5SQLServer的并發控制機制③排它(X):用于數據修改操作例如insert、update或delete。加排它鎖后其它事務不能讀取或修改排它鎖鎖定的數據。確保不會同時對同一資源進行多重更新;④意向(I):用于建立鎖的層次結構。意向鎖又細分為:意向共享(IS)、意向排它(IX)以及與意向排它共享(SIX)。BACK7.3.5SQLServer的并發控制機制

在transact-sql語句使用中有如下缺省加鎖規則:select查詢缺省時請求獲得共享鎖(頁級或表級);insert語句總是請求獨占的頁級鎖;update和delete查詢通常獲得某種類型的獨占鎖以進行數據修改;如果當前將被修改的頁上存在讀鎖,則delete或update語句首先會得到修改鎖,當讀過程結束以后,修改鎖自動改變為獨占鎖。BACK7.3.5SQLServer的并發控制機制可以使用select、insert、update和delete語句指定表級鎖定提示的范圍,以引導SQLServer使用所需的鎖類型。當需要對對象所獲得鎖類型進行更精細控制時,可以使用手工鎖定提示如:holdlock、nolock、paglock、readpast、rowlock、tablock、tablockx、updlock、xlock等,這些鎖定提示取代了會話的當前事務隔離級別指定的鎖。例如查詢時,可強制設定加獨占鎖,命令為:selectsnofromstudentwith(tablockx)wheredept='CS'BACK7.3.5SQLServer的并發控制機制SQLServer具有多粒度鎖定能力,允許一個事務鎖定不同類型的資源。為了使鎖定的成本減至最少,SQLServer自動將資源鎖定在適合任務的級別。鎖定在較小的粒度(例如行)可以增加并發但需要較大的開銷,因為如果鎖定了許多行,則需要控制更多的鎖。鎖定在較大的粒度(例如表)就并發而言是相當昂貴的,因為鎖定整個表限制了其它事務對表中任意部分進行訪問,但要求的開銷較低,因為需要維護的鎖較少。BACK7.3.5SQLServer的并發控制機制SQLServer可以鎖定以下資源,見表7.13。表7.13資源加鎖粒度表資源描述RID行標識符。用于單獨鎖定表中的一行。鍵索引中的行鎖。用于保護可串行事務中的鍵范圍。頁8千字節(KB)的數據頁或索引頁。擴展盤區相鄰的八個數據頁或索引頁構成的一組。表包括所有數據和索引在內的整個表。DB數據庫。BACK7.3.5SQLServer的并發控制機制

事務準備接受不一致數據的級別稱為隔離級別。隔離級別是一個事務必須與其它事務進行隔離的程度。較低的隔離級別可以增加并發,但代價是降低數據的正確性。相反,較高的隔離級別可以確保數據的正確性,但可能對并發產生負面影響。應用程序要求的隔離級別確定了SQLServer使用的鎖定行為。如:settransactionisolationlevelrepeatableread--設置為可重復讀BACK7.3.5SQLServer的并發控制機制SQL-92定義了下列四種隔離級別,如下由低到高的四種隔離級別:readuncommitted、readcommitted、repeatableread、serializable,默認情況下,SQLServer在readcommitted隔離級別上操作。但是應用程序可能必須運行于不同的隔離級別。若要在應用程序中使用更嚴格或較寬松的隔離級別,可以使用Transact-SQL或通過數據庫API來設置事務隔離級別,來自定義整個會話的鎖定。如:settransactionisolationlevelrepeatableread--設置為可重復讀BACK7.3.5SQLServer的并發控制機制隔離級別含義如下:①readuncommitted:執行臟讀或0級隔離鎖定,這表示事務中不發出共享鎖,也不接受排它鎖。當設置該選項時,可以對數據執行未提交讀或臟讀;在事務結束前可以更改數據內的數值,行也可以出現在數據集中或從數據集消失。該選項的作用與在事務內所有語句中的所有表上設置nolock相同。這是四個隔離級別中限制最小的級別。②readcommitted:指定在讀取數據時控制共享鎖以避免臟讀,但數據可在事務結束前更改,從而產生不可重復讀取或幻影數據。該選項是SQLServer的默認值。

BACK7.3.5SQLServer的并發控制機制③repeatableread:鎖定查詢中使用的所有數據以防止其他用戶更新數據,但是其他用戶可以將新的幻影行插入數據集,且幻影行包括在當前事務的后續讀取中。④

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論