【數據庫】1.mysql相關知識(六)

數據庫設計

1. 軟件項目開發週期中的數據庫設計

  • 需求分析階段:分析客戶的業務和數據處理需求
  • 概要設計階段:設計數據庫的E-R模型圖,確認需求的正確和完整性
  • 詳細設計階段:應用三大範式審覈數據庫
  • 代碼編寫階段:物理實現數據庫,編碼實現應用
  • 軟件測試階段
  • 安裝部署

2. 設計數據庫的步驟

2.1 收集信息

  • 與相關人員進行交流、訪談充分了解用戶需求,理解數據庫需要完成的任務

2.2 標示實體(Entity)

  • 標識數據庫要管理的關鍵對象或者實體,實體一般是名詞

2.3 標示實體的屬性(Attribute)

2.4 標示實體之間的關係(RelationShip)

3. 數據庫ER圖

  • ER圖:實體關係同,簡記E-R圖,是指以實體、關係、屬性三個基本概念概括數據的基本結構,從而描述靜態數據結構的概念模式
符號 含義
長方形
實體,一般是名詞
橢圓形
屬性,一般是名詞
菱形
關係,一般是動詞

3.1 ER圖的實體(entity)

  • ER圖的實體(entity)即數據模型中的數據對象,例如人、學生、音樂都可以作爲一個數據對象,用長方形來表示

3.2 ER圖的屬性(attribute)

  • ER圖的屬性(attribute)即數據對象所具有的屬性,例如學生具有姓名、學好、年級等屬性,用橢圓形表示
  • 屬性分類
    • 唯一屬性:唯一可用來標識該實體實例或成員的屬性,用下劃線表示,一般來講實體至少有一個唯一屬性。
    • 非唯一屬性

3.3 ER圖的關係(relationship)

  • ER圖的關係用來表現數據對象和數據對象之間的聯繫
  • 例如:
    • 學生的實體和成績表的實體之間有一定的聯繫,每個學生都有自己的成績表,這就是一種關係,關係用菱形來表示

3.4 ER圖中的關聯關係

3.4.1 1對1(1:1)
  • 1對1關係,指:
    • 對於實體集合A與實體集合B,A中的每一個實體之多與B中一個實體有關係;反之,在實體B中的每個實體至多與實體集A中有一個實體關係。
學生
身份證信息
  • X ---------------------------------------------------Y
  • X ---------------------------------------------------Y
  • X ---------------------------------------------------Y
  • X ---------------------------------------------------Y
3.4.2 1對多(1:N)
  • 1對多關係,指
    • 實體集A和實體集B中至少有N(N>0)個實體有關係;並且實體B中每一個實體至多與實體A中一個實體有關係
      在這裏插入圖片描述
3.4.3 多對多(M:N)
  • 多對多,指的是
    • 實體集A中的每一個實體與實體集B至少有M(M>0)個實體有關係,並且實體集B中的每一個實體與實體集A中的至少N(N>0)個實體有關係。
      在這裏插入圖片描述


4 數據庫設計的三大範式

4.1 不合理的表設計

  • 信息重複
  • 更新異常
  • 插入異常
  • 刪除異常

4.2 三大範式

4.2.1 第一範式(1NF)

  • 數據表中的每一列(每一個字段)都必須是不可拆分的最小單元,也就是確保每一列的原子性
ID 地址
1 中國上海
2 美國曼哈頓
3 英國倫敦
4 日本大阪

應該根據第一範式轉化爲:

ID 國家 城市
1 中國 上海
2 美國 曼哈頓
3 英國 倫敦
4 日本 大阪

4.2.2 第二範式(2NF)

  • 滿足1NF後,要求表中的所有列,都必須依賴於主鍵,而不能有任何一列與主鍵沒有關係,也就是說一個表只能描述意見事情

  • 舉例:如下訂單表,主鍵是訂單編號,就不滿足第二範式要求,因爲:

    • 每列都需要跟主鍵有關,而身份證號等個人信息那麼多,跟訂單編號沒有關係
    • 一個人同時頂幾個房間,就會出來一個訂單號多條數據,這樣子聯繫人都是重複的,就會造成數據冗餘
    • 所以可以轉成一張訂單表跟一張聯繫人表,如下面第二和第三張表
訂單編號 房間號 聯繫人 聯繫人電話 身份證號

優化後的表有如下兩張:

訂單編號 房間號 聯繫人編號
以上是訂單表
聯繫人編號 聯繫人 聯繫人電話 身份證
以上是聯繫人表

4.2.3 第三範式(3NF)

  • 滿足2NF後,要求:表中的每一列只與主鍵又直接關係,而不是間接關係(表中的每一列只能依賴於主鍵)
  • 數據不能存在傳遞關係,即每個屬性都跟主鍵又直接關係而不是間接關係
學生編號 學生姓名 年級ID 年級名稱
1 張三 1 年級

主鍵爲學生編號,學生姓名依賴主鍵,年級ID依賴主鍵,但是年級名稱是依賴年級ID,而不是直接依賴主鍵學生編號,所以需要拆分成如下兩個表

學生編號 學生姓名 年級ID
1 張三 1
以上是學生表
年級ID 年級名稱
1 一年級
以上是年級表

4.2.4 如何更好的區分三大範式

  • 第一範式和第二範式的區別在於有沒有分出兩張表,第二範式是說明第一張表中包含了多種不同的實體屬性,那麼要必須分成多張表
  • 第三範式是要求已經分成了多張表,那麼一張表中只能有另一張表中的id(主鍵)。而不能有其他的任何信息(其他的信息一律用未安檢在另一張表的主鍵查看)

5. RBAC

  • 基於角色的權限訪問控制(Role-Based Access Control)
  • RBAC就是用戶通過角色與權限進行關聯
  • 簡單地說,一個用戶擁有若干橘色,每個橘色擁有若干權限,每個權限可以操作若干資源,這樣就構造成"用戶-角色-權限-資源"的授權模型
  • 在這種模型中,用戶與角色之間,橘色與權限之間,權限與資源之間,一般都是多對多的關係
  • 在RBAC中最重要的概念包括:用戶(User)、角色(Role)、權限(Permission)、資源(Resource)

5.1 安全原則

  • 最小權限原則
    • RBAC可以將其角色配置成其完成任務所需要的最小的權限集
  • 責任分離原則
    • 可以通過互斥的角色來共同完成敏感的任務
      • 比如:記賬員和財務管理員共同過賬
  • 數據抽象可以通過權限的抽象來體現
    • 比如財務操作用借款、存款等來替代操作系統提供的典型的讀、寫、執行權限。

6. 事務

6.1 爲什麼需要事務

  • 銀行轉賬問題
  • A賬戶資金減少
  • B賬戶資金增加
    CREATE DATEBASE bank;
    use bank;
    CREATE TABLE account
    (
        name varchar(64),
        balance decimal(10,2)
    )
    INSERT INTO account(name,balance) VALUES('張三',100);
    INSERT INTO account(name,balance) VALUES('李四',100);

    UPDATE account SET balance = balance - 10 WHERE name = '張三';
    UPDATE account SET balance = balance + 10 WHERE name = '李四';

6.2 什麼是事務

  • 事務是作爲單個邏輯工作單元執行的一系列操作
  • 多個操作作爲一個整體向系統提交,要麼都執行,要麼都不執行
  • 事務是一個不可分割的工作邏輯單元

轉賬過程就是一個整體,它需要兩條UPDATE語句,如果任何一個出錯,則整個轉賬業務取消,兩個賬戶餘額都恢復到原來的數據,確保總月不變

6.3 事務的特性ACID

  • 原子性(Atomicity)事務是一個完整的操作,事務各個部分是不可分的,要麼都執行,要麼都不執行
  • 一致性(Consistency)當事務完成後,數據必須處理完整的狀態
  • 隔離性(Isolation)併發事務彼此隔離、獨立,他不應該以任何方式依賴於其他事務
  • 持久性(Durability)事務完成後,它對數據庫的修改被永久保持

6.4 如何創建事務

  • 開始事務 START TRANSACTION 或者 BEGIN
  • 提交事務 COMMIT
  • 關閉/開啓自動提交狀態 SET AUTOCOMMIT=0/1 0關閉 1開啓

關閉自動提交後,從嚇一跳SQL語句開始開啓新的事務,需要使用COMMIT或ROLLBACK結束該事務

7. 鎖

  • 鎖時計算機協調多個進程或線程併發訪問某一資源的機制

7.1 鎖的分類

  • 從對數據庫操作的類型分類,分爲:
    • 讀鎖(共享鎖):針對同一份數據,多個讀操作可以同時進行而不會相互影響,但是不能刪除跟修改
    • 寫鎖(排它鎖):當前寫操作沒有完成前,它會阻斷其他寫鎖和讀鎖,也就是我寫完前,別人不能讀也不能寫
      • 讀鎖會阻塞寫,但不會阻塞讀;而寫鎖則會把讀和寫都阻塞。
  • 從對數據操作的粒度分,分爲
    • 表鎖:把整個表鎖住,別人就不能操作表內的任何內容
    • 行鎖:可以鎖定某一行,鎖定的行,別人不能操作,其他沒鎖定的可以操作

8.2 表鎖

- 表鎖偏向MyISAM存儲引擎,開銷小,加鎖快,鎖定粒度大,發生鎖衝突的概率最高,併發度最低
    - MyISAM存儲引擎:操作非常快,但不支持事務
    - INNODB存儲引擎:操作慢,但支持事務
- 語法:
    - 加一個鎖:LOCK TABLE 表名1 read(write),表名2 read(write);
        - read表示加的是讀鎖
        - write表示加的是寫鎖
    - 解鎖:UNLOCK TABLES;

8.2.1 表鎖舉例:

  1. 準備數據
    CREATE TABLE users(
        id INT(11) NOT NULL AUTO_INCREMENT,
        name VARCHAR(20) DEFAULT NULL,
        PRIMARY KEY(id)
    )ENGINE=MyISAM DEFALUT CHARSET=utf8;
    INSERT INTO users(id,name) VALUES(1,'a');
    INSERT INTO users(id,name) VALUES(2,'b');
    INSERT INTO users(id,name) VALUES(3,'c');
    INSERT INTO users(id,name) VALUES(4,'d');

    LOCK TABLE 表名1 read(write),表名2 read(write);

8.3 行鎖

- 行鎖偏向InnoDB存儲引擎,開銷大,加鎖慢,會出現死鎖,鎖定粒度小,發生鎖衝突的概率最低,併發度也最高
- InnoDB與MYISAM的最大不同是:
    - 前者支持事務,後者不支持
    - 前者採用了行級鎖,後者是表級鎖

8.3.1 行鎖支持事務

8.3.1.1 併發事務處理帶來的問題

8.3.1.1.1 更新丟失(Lost Update)
  • 當兩個或多個事務選擇同一行,然後基於最初選定的值更新該行時,由於每個事務都不知道其他事務的存在,就會發生丟失更新問題——最後的更新覆蓋了由其他事務所做的更新。

  • 後面的事務覆蓋了前面的值

  • 舉例:

    • A同學建立了一個事務,正在修改數據,且沒有提交。B同學也建立了一個事務,也在修改數據,且沒有提交。
        //A同學
            set autocommit=0;//關閉自動提交
            begin;
            select * from user;
            update user set age = 90 where name='張三';
            //此時正在修改,並沒有commit提交
    
        //B同學
            set autocommit=0;//關閉自動提交
            begin;
            select * from user;
            update user set age = 80 where name='張三';
            //此時正在修改,並沒有commit提交
    
    • 這時候A先提交,B也提交了。
      • A提交完,張三是90歲,B提交完,張三成了80歲。B的提交覆蓋了A的提交,而A並不知道B在提交,所以A以爲現在張三還是90歲,其實已經被後提交的事務覆蓋成了80歲。
8.3.1.1.2 髒讀(Dirty Reads)
  • 一個事務正在對一條記錄做修改,在這個事務完成並提交前,這條記錄的數據就處於不一致的狀態;這時,另一個事務也來讀取同一條記錄,如果不加控制,第二個事務讀取了這些“髒”數據,並據此作進一步的處理,就會產生未提交的數據依賴關係。這種現象叫做“髒讀”
  • 一句話:事務A讀取了事務B已經修改但尚未提交數據,還在這個數據基礎上做了操作。此時,如果B事務回滾,A讀取的數據無效,不符合一致性要求。
  • 髒讀是事務B修改了數據,這是不正常的
  • 解決辦法:如果在第一個事務提交前,任何其他事務不可讀取其修改過的值,則可以避免該問題。
8.3.1.1.3 不可重複讀(Non-Repeatable Reads)
  • 一個事務在讀取某些數據後的某個時間,再次讀取以前讀過的數據,卻發現其讀出的數據已經發生了改變、或某些記錄已經被刪除了!這種現象叫"不可重複讀"。
  • 一句話:事務A讀取到了事務B已經提交的修改數據,不符合隔離性,這是不正常的。
  • 解決辦法:如果只有在修改事務完全提交之後纔可以讀取數據,則可以避免該問題。
8.3.1.1.4(Phantom Reads)
  • 一個事務按相同的查詢條件重新讀取以前檢索過的數據,卻發現其他事務插入了滿足其查詢條件的新數據,這種現象就成爲“幻讀”。
  • 一句話:事務A讀取到了事務B提交的新增數據,不符合隔離性
  • 幻讀是事務B裏面新增了數據,這是不正常的
  • 解決辦法:如果在操作事務完成數據處理之前,任何其他事務都不可以添加新數據,則可避免該問題。
8.3.1.2 事務隔離四種級別
  • read uncommited:讀取尚未提交的數據:就是髒讀
  • read committed:讀取已經提交的數據:可以解決髒讀
  • repeatable read:重讀讀取:可以解決髒讀和不可重複讀 (mysql默認的)
  • serializable:串行化:解決髒讀、不可重複讀和幻讀 (相當於鎖表)
8.3.1.2.1 事務隔離操作
  • 查看當前表的事務隔離等級
    SELECT @@tx_isolation;
  • 修改表的事務隔離等級
    set session transaction isolation level read uncommitted;//修改成了髒讀等級

8.3.2 死鎖

  • A在修改數據庫,B想改A在改的那個數據庫,那麼B是修改不了的,要等A釋放,B纔可以修改。這就是死鎖。
  • 鎖的學問很大,可以自己學習。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章