存放數據的倉庫。例如你的帳號信息,訂單記錄等。mysql
Structured Query Language,用於訪問和處理關係數據庫的標準的計算機語言。sql
按照功能又可分爲四大類;數據庫
查詢語言,基本語句 SELECT;性能優化
操縱語言,主要有三種形式,INSERT、UPDATE 和 DELETE;數據結構
定義語言,建立表、視圖、索引等,CREATE TABLE;併發
控制語言,用來受權或回收某種特權,基本形式有 GRANT、 COMMIT 和 ROLLBACK;分佈式
Not Only SQL,泛指非關係型的數據庫,一般以鍵值對或者文檔形式存儲。例如 Redis、MongoDB。性能
關係型數據庫(MySQL)能經過外鍵創建表之間的聯繫,且相比 NoSQL 而言,還具有 ACID 特性。優化
但 NoSQL 操做無須 SQL 解析,讀寫性能較高,相比關係型數據庫來講,不用預設存儲結構,且自然支持分佈式存儲。ui
數據庫知足必定要求的條件稱爲數據庫範式。又能根據程度的不一樣,簡稱爲第 N 範式。
全部屬性不可再分,例如屬性 product 就不能分爲 title 和 price,能夠單獨設置兩個屬性 productTitle、productPrice;
每張表都有一個屬性做爲惟一標識,其餘屬性徹底依賴該標識,例如自增主鍵ID;
全部的非主屬性不依賴於其餘的非主屬性。例如訂單表中能夠關聯商品ID,但不該該關聯商品非主屬性 title 和 price 等;
爲了提升查詢效率,一般會添加冗餘字段,這也就違背了 3NF,也稱之爲反三範式。
MySQL 是一個 Oracle 旗下的關係型數據庫,使用 SQL 語言進行增刪改查操做。
開源免費,性能也比較好,和 PHP、Java 等 Web 開發語言完美配合,在中小型企業應用很是普遍。
後續內容都是基於 MySQL 數據庫的前提下。
常見的有 MyISAM 和 InnoDB 引擎;
引擎 | 默認版本 | 外鍵 | 鎖粒度 | count(*) | 事務 |
---|---|---|---|---|---|
MyISAM | < 5.5 | 不支持 | 表鎖 | 變量存儲 | 不支持 |
InnoDB | >= 5.5 | 支持 | 行鎖 | 全表掃描 | 支持 |
一條或多條 SQL 組成一個事務(transaction),具有 ACID 四個特性;
一個事務內的全部操做,要麼所有完成,要麼所有失敗;
事務開始先後結束後不會破壞數據庫的完整性,也就是說寫入或修改的結構須要符合預設的規則;
防止事務交叉執行時致使數據的不一致。根據隔離程度分爲 read uncommitted、read committed、repeatable read 和 serializable;
事務結束後,對數據的修改是永久的;
事務交叉執行可能會形成「髒讀」、「幻讀」 和 「不可重複讀」;
一個事務讀取到另一個事務還未提交的數據;
一個事務內,屢次讀取同一數據返回結果不一樣;因爲在此期間在數據被其餘事務修改並已提交;
一個事務內,屢次讀取,返回不存在的記錄;因爲在此期間有其餘事務寫入數據;
read uncommitted | read committed | repeatable read | serializable | |
---|---|---|---|---|
髒讀 | √ | × | × | × |
不可重複讀 | √ | √ | × | × |
幻讀 | √ | √ | √ | × |
數據庫的「目錄」,在數據量較大的狀況下,能夠極大地提升查詢效率。
常見的索引數據結構有 B+ 樹、Hash。以最經常使用的 B+ 樹爲例;
按照 B+ 樹存儲方式能夠把索引分爲兩大類;
葉子節點存放了一整行的信息;
葉子節點存放的是對應那行數據的主鍵,和該索引的值;
爲何是 B+ 樹?
- 磁盤代價低;
- 查詢更加穩定;
- 便於遍歷;
- 支持範圍查詢;
一張結構爲 id,groupId,name 的 t_user 表,id 爲主鍵(聚簇索引),groupId 爲普通索引(非聚簇索引)。
select name from t_user where groupId = 123;
先在葉子節點上獲得對應的主鍵 id,而後再根據主鍵 id 獲得 name 的值,這種行爲稱之爲回表。
select groupId from t_user where groupId = 123;
直接在葉子節點上就能獲得 groupId 的值,不用回表操做,這種索引也被稱爲覆蓋索引。
按照功能類型又能夠把索引分爲三大類;
最基本的索引類型,沒有限制條件;
保證索引字段的值惟一,容許有 NULL;主鍵是一種特殊的惟一索引,不容許有 NULL;
多個字段組成一個索引,具備「最左前綴」的原則;
什麼是最左前綴?a、b、c 三個字段組成聯合索引,那麼生效的列爲 a、ab、abc、ac。(等值判斷時順序可交換,範圍查詢時會中止匹配)
宏觀來看,鎖分爲兩種;行鎖可概括爲兩類;
share,又稱爲讀鎖,已有 S 鎖,能夠加其餘 S 鎖,但不能加 X 鎖;
exclusive,又稱爲寫鎖,X 與其餘任何鎖互斥;
InnoDB 是經過給索引項加鎖實現的行鎖,可分爲三種類型;
行級鎖,鎖定對應索引項;
間隙鎖,鎖定索引項之間的間隙,左開右閉;
前兩種的結合;
若是不經過索引項檢索數據,會鎖住整個表。
InnoDB 加鎖方法:
查詢當前數據庫鎖狀態;
select * from information_schema.innodb_locks;
對於不一樣類型的索引,加鎖的方式也不同;
加 next-key lock;
加 record lock;
因爲普通索引葉子節點存儲了主鍵,因此加鎖的字段是:普通索引 + 主鍵索引;
假設有以下數據表 t_ lock,其中 id 爲主鍵,xid 爲 普通索引;
+-----+----+ | xid | id | +-----+----+ | 1 | 10 | | 3 | 20 | | 5 | 30 | | 8 | 40 | | 11 | 50 | +-----+----+
給 (8, 40) 這條記錄加 X 鎖;
select * from t_lock where xid = 8 for update;
那麼根據 next-key lock 的定義,鎖住區間爲 (5, 30) 到 (8, 40),(8, 40) 到 (11, 50) 這兩個區間;
便於理解我會合併爲一個區間 (5, 30) 到 (11, 50)。
按照因此排序規則,假設另插入 (xid, id) 記錄,那麼老是知足如下條件;
簡單圖示,當插入的數據落在這個區間則會阻塞,反之亦然;
上面事務章節描述 RR 會致使幻讀,MySQL 在 RR 下經過以下兩點規避掉了;
Multi-Version Concurrency Control,多版本併發控制。在普通 SELECT (快照度)時引入版本,同一個事務中只能讀取不大於當前版本的數據快照;
須要加 X 鎖的操做(當前讀),加 next-key lock 能夠有效避免產生幻讀;
根據建立時間升序,查找支付成功超過 3 單的用戶,須要去重;
select distinct t1.nickname from t1 inner join t2 on t1.uid = t2.uid where t2.pay_time > 0 group by t1.uid, t1.nickname having count(*) > 3 order by t2.create_time limit 10
binlog 是 MySQL 最重要的日誌,記錄了全部的 DDL 和 DML 語句,主要目的是;
在 Master 開啓 binlog,並傳遞到 Slave 節點來達到 Master-Slave 數據一致性;
經過 mysqlbinlog 恢復數據;
檢查 binlog 是否開啓;
show variables like 'log_bin';
編輯 mysql 配置文件/etc/mysql/mysql.conf.d/mysqld.cnf
,開啓 binlog 功能;
[mysqld] server-id=1 log-bin=/var/lib/mysql/mysql-bin
經常使用幾個命令;
例如誤刪除了某條記錄;
可直接流式執行:mysqlbinlog -v --start-position 2432 --stop-position 2533 mysql-bin.000003 | mysql -uroot -p
mysqldump 是用來備份數據庫的,例如備份 db_test 數據庫;
mysqldump -h127.0.0.1 -uroot -p123456 db_test > db.sql
給常常用做查詢條件,且區分度較高的字段創建索引;
where id > ${lastId} order by id limit ${size},提升大表分頁效率;
批量插入用 insert into xxx values (xxx...), (xxx...),批量更新用 case when id;
null 會額外佔用空間,且 count(xxx) 不會參與統計,如果索引列 is not null 也會失效;