文章目錄
關係模型和SQL
- 下面以Mysql數據庫爲例介紹關係模型
安裝
MariaDB安裝
yum list | grep mariadb #查看
yum install mariadb-server #安裝
systemctl start mariadb.server #啓動
ss -tanl #查看狀態, 確認啓動成功
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 50 *:3306 *:*
systemctl enable mariadb.server #設置開機啓動
mysql_secure_installation #進行安全設置
mysql -u root -p < test.sql #導入測試版本
mysql -u root -p < scripts/mysql.sql #在gogs目錄下執行, 就是創建了gogs庫
mysql -u root -p #數據庫root賬戶密碼登錄
show databases; #列出所有庫
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)
grant all on *.* to '用戶名'@'%' identified by '密碼'; #創建並授權用戶(*.*:權限範圍, 本命令中的權限是所有庫所有文件)
flush privileges; #刷新
SQL語句
SQL是結構化查詢語言Structured Query Language。1987年被ISO組織標準化
所有主流的關係型數據庫都支持SQL,NoSQL也有很大一部分支持SQL
SQL語句分爲:
- 數據定義語言,負責數據庫定義、數據庫對象定義,由CREATE、 與DROP三種語句組成
- DML數據操作語言,負責對數據庫對象的操作,CRUD增刪改查
- DCL數據控制語言,負責數據庫權限訪問控制,由 GRANT 和 REVOKE 兩個指令組成
- TCL事務控制語言,負責處理ACID事務,支持commit、rollback指令
語言規範:
- SQL語句大小寫不敏感
- 一般建議,SQL的關鍵字、函數等大寫
- SQL語句末尾應該使用分號結束
- 註釋
- 多行註釋 /註釋內容/
- 單行註釋 – 註釋內容
- MySQL 註釋可以使用#
- 使用空格或縮進來提高可讀性
- 命名規範
- 必須以字母開頭
- 可以使用數字、#、$和_
- 不可使用關鍵字
DCL
GRANT授權、REVOKE撤銷
GRANT ALL ON employees.* TO 'wayne'@'%' IDENTIFIED by 'wayne';
REVOKE ALL ON *.* FROM wayne;
* 爲通配符,指代任意庫或者任意表。 *.* 所有庫的所有表; employees.* 表示employees庫下所有的表
% 爲通配符,它是SQL語句的通配符,匹配任意長度字符串
DDL
刪除用戶(慎用)
DROP USER wayne;
創建數據庫
庫是數據的集合,所有數據按照數據模型組織在數據庫中
CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8;
CHARACTER SET指定字符集
utf8mb4是utf8的擴展,支持4字節utf8mb4,需要MySQL5.5.3+
COLLATE指定字符集的校對規則,用來做字符串的比較的。例如a、A誰大?
刪除數據庫
DROP DATABASE IF EXISTS gogs;
創建表
表分爲行和列,MySQL是行存數據庫。數據是一行行存的,列必須固定多少列
行Row,也稱爲記錄Record,元組
列Column,也稱爲字段Field、屬性
字段的取值範圍叫做 域Domain。例如gender字段的取值就是M或者F兩個值
![圖片]
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` enum('M','F') NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
反引號標註的名稱,會被認爲是非關鍵字,使用反引號避免衝突
DESC
查看列信息
{DESCRIBE | DESC} tbl_name [col_name | wild]
DESC employees;
DESC employees '%name';
關係
在關係數據庫中,關係就是二維表,由行和列組成
行Row,也稱爲記錄Record,元組
列Column,也稱爲字段Field、屬性
字段的取值範圍叫做 域Domain。例如gender字段的取值就是M或者F兩個值
維數:關係的維數指關係中屬性的個數
基數:元組的個數
注意在關係中,屬性的順序並不重要。理論上,元組順序也不重要,但是由於元組順序與存儲相關,會影響查詢效率
候選鍵
關係中,能唯一標識一條元組的屬性或屬性集合,稱爲候選鍵
PRIMARY KEY主鍵
表中一列或者多列組成唯一的key,也就是通過這一個或者多個列能唯一的標識一條記錄。即被選擇的候選鍵
主鍵的列不能包含空值null。主鍵往往設置爲整型、長整型,可以爲自增AUTO_INCREMENT字段
表中可以沒有主鍵,但是,一般表設計中,往往都會有主鍵,以避免記錄重複
Foreign KEY外鍵
嚴格來說,當一個關係中的某個屬性或屬性集合與另一個關係(也可以是自身)的候選鍵匹配時,就稱作這個屬性或屬性集合是外鍵
索引Index
可以看做是一本字典的目錄,爲了快速檢索用的。空間換時間,顯著提高查詢效率
可以對一列或者多列字段設定索引
主鍵索引,主鍵會自動建立主鍵索引,主鍵本身就是爲了快速定位唯一記錄的
唯一索引,表中的索引列組成的索引必須唯一,但可以爲空,非空值必須唯一
普通索引,沒有唯一性的要求,就是建了一個字典的目錄而已
在MySQL中,InnoDB和MyISAM的索引數據結構可以使用Hash或BTree,默認是BTree
Hash時間複雜度是O(1),但是隻能進行精確匹配,也就是Hash值的匹配,比如範圍匹配就沒辦法了,hash值無序所以無法知道原有記錄的順序。Hash問題較多
BTree索引,以B+樹爲存儲結構
雖然,索引可以提高查詢所讀,但是卻影響增刪改的效率,因爲需要索引更新或重構。頻繁出現在where子句中的列可以考慮使用索引。要避免把性別這種字段設索引
約束Constraint
爲了保證數據的完整正確,數據模型還必須支持完整性約束
“必須有值”約束
某些列的值必須有值,不許爲空NULL
域約束Domain Constraint
限定了表中字段的取值範圍
實體完整性Entity Integrity
PRIMARY KEY約束定義了主鍵,就定義了主鍵約束。主鍵不重複且唯一,不能爲空
引用完整性Referential Integrity ***
外鍵定義中,可以不是引用另一張表的主鍵,但是,往往實際只會關注引用主鍵
外鍵:在表B中的列,引用了表A中的主鍵,表B中的列就是外鍵
A表稱爲主表,B表稱爲從表
- 插入規則
不需要指定
如果在表B插入一條記錄,B的外鍵列插入了一個值,這個值必須是表A中存在的主鍵值
- 更新規則
定義外鍵約束時指定該規則 - 刪除規則
定義外鍵約束時指定該規則
外鍵約束的操作
設定值 | 說明 |
---|---|
CASCADE | 級聯,從父表刪除或更新會自動刪除或更新子表中匹配的行 |
SET NULL | 從父表刪除或更新行,會設置子表中的外鍵列爲NULL,但必須保證子表列沒有指定NOT NULL,也就是說子表的字段可以爲NULL纔行 |
RESTRICT | 如果從父表刪除主鍵,如果子表引用了,則拒絕對父表的刪除或更新操作 |
No ACTION | 標準SQL的關鍵字,在MySQL中與RESTRICT相同。拒絕對父表的刪除或更新操作 |
外鍵約束,是爲了保證數據完整性、一致性,杜絕數冗餘、數據錯誤
實體-聯繫E-R
數據庫建立,需要收集用戶需求,設計符合企業要求的數據模型。而構建這種模型需要方法,這種方法需要成爲E-R實體-聯繫建模。也出現了一種建模語言——UML(Unified Modeling Language)統一建模語言
實體Entity:現實世界中具有相同屬性的一組對象,可以是物理存在的事物或抽象的事物
聯繫Relationship:實體之間的關聯集合
實體間聯繫類型
類型 | 描述 | 解決方案 |
---|---|---|
一對多聯繫 1:n | 一個員工屬於一個部門,一個部門有多個員工 | 員工外鍵;部門主鍵 |
多對多聯繫 m:n | 一個員工屬於多個部門,一個部門有多個員工 | 建立第三表 |
一對一聯繫 1:1 | 假設有實體管理者,一個管理者管理一個部門,一個部門只有一個管理者 | 字段建在哪張表都行 |
一對一關係用的較少,往往表示表A的一條記錄唯一關聯表B的一條記錄,反之亦然
它往往是爲了將一張表多列分割併產生成了多張表,合起來是完整的信息,或爲了方便查詢,或爲了數據安全隔離
一部分字段的數據等等
視圖
視圖,也稱虛表,看起來像表。它是由查詢語句生成的。可以通過視圖進行CRUD操作
視圖的作用
-
簡化操作,將複雜查詢SQL語句定義爲視圖,可以簡化查詢
-
數據安全,視圖可以只顯示真實表的部分列,或計算後的結果,從而隱藏真實表的數據
數據類型
MySQL中的數據類型
類型 | 含義 |
---|---|
tinyint | 1字節,帶符號的範圍是-128到127。無符號的範圍是0到255。bool或boolean,就是tinyint,0表示假,非0表示真 |
smallint | 2字節,帶符號的範圍是-32768到32767。無符號的範圍是0到65535 |
int | 整型,4字節,同Integer,帶符號的範圍是-2147483648到2147483647。無符號的範圍是0 到4294967295 |
bigint | 長整型,8字節,帶符號的範圍是-9223372036854775808到9223372036854775807。無符號的範圍是0到18446744073709551615 |
float | 單精度浮點數精確到大約7位小數位 |
double | 雙精度浮點數精確到大約15位小數位 |
DATE | 日期。支持的範圍爲’1000-01-01’到’9999-12-31’ |
DATETIME | 支持的範圍是’1000-01-01 00:00:00’到’9999-12-31 23:59:59’ |
TIMESTAMP | 時間戳。範圍是’1970-01-01 00:00:00’到2037年 |
char(M) | 固定長度,右邊填充空格以達到長度要求。M爲長度,範圍爲0~255。M指的是字符個數 |
varchar(M) | 變長字符串。M 表示最大列長度。M的範圍是0到65,535。但不能突破行最大字節數65535 |
text | 大文本。最大長度爲65535(2^16-1)個字符 |
BLOB | 大字節。最大長度爲65535(2^16–1)字節的BLOB列 |
LENGTH函數返回字節數。而char和varchar定義的M是字符數限制
char可以將字符串定義爲固定長度,空間換時間,效率略高;varchar爲變長,省了空間
關係操作
關係:在關係數據庫中,關係就是二維表
關係操作就是對錶的操作
選擇(selection):又稱爲限制,是從關係中選擇出滿足給定條件的元組
投影(projection):在關係上投影就是從選擇出若干屬性列組成新的關係
連接(join):將不同的兩個關係連接成一個關係
DML —— CRUD 增刪改查
nsert語句
INSERT INTO table_name (col_name,...) VALUES (value1,...);
-- 向表中插入一行數據,自增字段、缺省值字段、可爲空字段可以不寫
INSERT INTO table_name SELECT ... ;
-- 將select查詢的結果插入到表中
INSERT INTO table_name (col_name1,...) VALUES (value1,...) ON DUPLICATE KEY UPDATE col_name1=value1,...;
-- 如果主鍵衝突、唯一鍵衝突就執行update後的設置。這條語句的意思,就是主鍵不在新增記錄,主鍵在就更新部分字段
INSERT IGNORE INTO table_name (col_name,...) VALUES (value1,...);
-- 如果主鍵衝突、唯一鍵衝突就忽略錯誤,返回一個警告
INSERT INTO reg (loginname, `name`, `password`) VALUES ('tom', 'tom', 'tom');
INSERT INTO reg (id, loginname, `name`, `password`) VALUES (5, 'tom', 'tom', 'tom');
INSERT INTO reg (id, loginname, `name`, `password`) VALUES (1, 'tom', 'tom', 'tom') ON DUPLICATE KEY UPDATE name = 'jerry';
Update語句
UPDATE [IGNORE] tbl_name SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition]
-- IGNORE 意義同Insert語句
UPDATE reg SET name='張三' WHERE id=5;
-- 注意這一句非常危險,會更新所有數據
UPDATE reg SET name = 'ben';
-- 更新一定要加條件
UPDATE reg SET name = 'ben', password = 'benpwd' WHERE id = 1;
Delete語句
DELETE FROM tbl_name [WHERE where_definition]
-- 刪除符合條件的記錄
-- 刪除一定要有條件
DELETE FROM reg WHERE id = 1;
Select語句
SELECT
[DISTINCT]
select_expr, ...
[FROM table_references
[WHERE where_definition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_definition]
[ORDER BY {col_name | expr | position}
[ASC | DESC] , ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[FOR UPDATE | LOCK IN SHARE MODE]]
FOR UPDATE會把行進行寫鎖定,這是排它鎖
查詢
查詢的結果成爲結果集recordset
SELECT 1;
-- 最簡單的查詢
SELECT * FROM employees;
-- 字符串合併
SELECT emp_no, first_name + last_name FROM employees;
SELECT emp_no, CONCAT(first_name,' ',last_name) FROM employees;
-- AS 定義別名,可選。寫AS是一個好習慣
SELECT emp_no as `no`, CONCAT(first_name,' ',last_name) name FROM employees emp;
Limit子句
-- 返回5條記錄
SELECT * FROM employees emp LIMIT 5;
-- 返回5條記錄,偏移18條
SELECT * FROM employees emp LIMIT 5 OFFSET 18;
SELECT * FROM employees emp LIMIT 18, 5;
Where子句
運算符 | 描述 |
---|---|
= | 等於 |
<> | 不等於 |
>、<、>=、<= | 大於、小於、大於等於、小於等於 |
BETWEEN | 在某個範圍之內,between a and b等價於[a, b] |
LIKE | 字符串模式匹配,%表示任意多個字符,_表示一個字符 |
IN | 指定針對某個列的多個可能值 |
AND | 與 |
OR | 或 |
注意:如果很多表達式需要使用AND、OR計算邏輯表達式的值的時候,由於有結合律的問題,建議使用小括號來避免產生錯誤
-- 條件查詢
SELECT * FROM employees WHERE emp_no < 10015 and last_name LIKE 'P%';
SELECT * FROM employees WHERE emp_no BETWEEN 10010 AND 10015 AND last_name LIKE 'P%';
SELECT * FROM employees WHERE emp_no in (10001, 10002, 10010);
Order by子句
對查詢結果進行排序,可以升序ASC、降序DESC
-- 降序
SELECT * FROM employees WHERE emp_no in (10001, 10002, 10010) ORDER BY emp_no DESC;
DISTINCT
不返回重複記錄
-- DISTINCT使用
SELECT DISTINCT dept_no from dept_emp;
SELECT DISTINCT emp_no from dept_emp;
SELECT DISTINCT dept_no, emp_no from dept_emp;
聚合函數
函數 | 描述 |
---|---|
COUNT(expr) | 返回記錄中記錄的數目,如果指定列,則返回非NULL值的行數 |
COUNT(DISTINCT expr,[expr…]) | 返回不重複的非NULL值的行數 |
AVG([DISTINCT] expr) | 返回平均值,返回不同值的平均值 |
MIN(expr), MAX(expr) | 最小值,最大值 |
SUM([DISTINCT] expr) | 求和,Distinct返回不同值求和 |
-- 聚合函數SELECT COUNT(*), AVG(emp_no), SUM(emp_no), MIN(emp_no), MAX(emp_no) FROM employees;
分組查詢
使用Group by子句,如果有條件,使用Having子句過濾分組、聚合過的結果
-- 聚合所有
SELECT emp_no, SUM(salary), AVG(salary), COUNT(emp_no) from salaries;
-- 聚合被選擇的記錄
SELECT emp_no, SUM(salary), AVG(salary), COUNT(emp_no) from salaries WHERE emp_no < 10003;
-- 分組
SELECT emp_no FROM salaries GROUP BY emp_no;
SELECT emp_no FROM salaries WHERE emp_no < 10003 GROUP BY emp_no;
-- 按照不同emp_no分組,每組分別聚合
SELECT emp_no, SUM(salary), AVG(salary), COUNT(emp_no) from salaries WHERE emp_no < 10003 GROUP BY emp_no;
-- HAVING子句對分組結果過濾
SELECT emp_no, SUM(salary), AVG(salary), COUNT(emp_no) from salaries GROUP BY emp_no HAVING AVG(salary) > 45000;
-- 使用別名
SELECT emp_no, SUM(salary), AVG(salary) AS sal_avg, COUNT(emp_no) from salaries GROUP BY emp_no HAVING sal_avg > 60000;
-- 最後對分組過濾後的結果排序
SELECT emp_no, SUM(salary), AVG(salary) AS sal_avg, COUNT(emp_no) from salaries GROUP BY emp_no HAVING sal_avg > 60000 ORDER BY sal_avg;
分組是將數據按照指定的字段分組,最終每組只能出來一條記錄。這就帶來了問題,每一組誰做代表,其實誰做代表都不合適
如果只投影分組字段、聚合數據,不會有問題,如果投影非分組字段,顯示的時候不能確定是組內誰的數據
-- 分組
SELECT emp_no, MAX(salary) FROM salaries; -- 10001 88958
SELECT emp_no, MIN(salary) FROM salaries; -- 10001 40006
上例很好的說明了使用了聚合函數,雖然沒有顯式使用Group By語句,但是其實就是把所有記錄當做一組,每組只能出一條,那麼一組也只能出一條,所以結果就一條
但是emp_no就是非分組字段,那麼它就要開始覆蓋,所以,顯示爲10001。當求最大值的時候,正好工資表中10001的工資最高,感覺是對的。但是,求最小工資的時候,明明最小工資是10003的40006,由於emp_no不是分組字段,導致最後被覆蓋爲10001
SELECT emp_no, MIN(salary) FROM salaries GROUP BY emp_no;
上句纔是正確的語義,按照不同員工emp_no工號分組,每一個人一組,每一個人有多個工資記錄,按時每組只能按照人頭出一條記錄
-- 單表較爲複雜的語句
SELECT
emp_no,
avg(salary) AS avg_salary
FROM
salaries
WHERE
salary > 70000
GROUP BY
emp_no
HAVING
avg(salary) > 50000
ORDER BY
avg_salary DESC
LIMIT 1;
子查詢
查詢語句可以嵌套,內部查詢就是子查詢
子查詢必須在一組小括號中
子查詢中不能使用Order by
-- 子查詢
SELECT * FROM employees WHERE emp_no in (SELECT emp_no from employees WHERE emp_no > 10015) ORDER BY emp_no DESC;
SELECT emp.emp_no, emp.first_name, gender FROM (SELECT * from employees WHERE emp_no > 10015) AS emp WHERE emp.emp_no < 10019 ORDER BY emp_no DESC;
連接Join
交叉連接cross join
笛卡爾乘積,全部交叉
在MySQL中,CROSS JOIN從語法上說與INNER JOIN等同
Join會構建一張臨時表
-- 工資40行
SELECT * FROM salaries;
-- 20行
SELECT * FROM employees;
-- 800行
SELECT * from employees CROSS JOIN salaries;
-- 隱式連接,800行
SELECT * FROM employees, salaries;
注意:salaries和employees並沒有直接的關係,做笛卡爾乘積只是爲了看的清楚
- 內連接
inner join,省略爲join
等值連接,只選某些field相等的元組(行),使用On限定關聯的結果
自然連接,特殊的等值連接,會去掉重複的列。用的少
-- 內連接,笛卡爾乘積 800行
SELECT * from employees JOIN salaries;
SELECT * from employees INNER JOIN salaries;
-- ON等值連接 40行
SELECT * from employees JOIN salaries ON employees.emp_no = salaries.emp_no;
-- 自然連接,去掉了重複列,且自行使用employees.emp_no = salaries.emp_no的條件
SELECT * from employees NATURAL JOIN salaries;
- 外連接
outer join,可以省略爲join
分爲左外連接,即左連接;右外連接,即右連接;全外連接
-- 左連接
SELECT * from employees LEFT JOIN salaries ON employees.emp_no = salaries.emp_no;
-- 右連接
SELECT * from employees RIGHT JOIN salaries ON employees.emp_no = salaries.emp_no;
-- 這個右連接等價於上面的左連接
SELECT * from salaries RIGHT JOIN employees ON employees.emp_no = salaries.emp_no;
左外連接、右外連接
SELECT * from employees RIGHT JOIN salaries ON employees.emp_no = salaries.emp_no;
結果是先employees後salaries的字段顯示,Right是看錶的數據的方向,從salaries往employees看,以salaries爲準,它的所有數據都顯示
- 自連接
表,自己和自己連接
select manager.* from emp manager,emp worker where manaer.empno=worker.mgr and worker.empno=1;
select manager.* from emp manager inner join emp worker on manaer.empno=worker.mgr where worker.empno=1;
存儲過程、觸發器
存儲過程(Stored Procedure),數據庫系統中,一段完成特定功能的SQL語句。編寫成類似函數的方式,可以傳參並調用。支持流程控制語句
觸發器(Trigger),由事件觸發的特殊的存儲過程,例如insert數據時觸發
這兩種技術,雖然是數據庫高級內容,性能不錯,但基本很少用了;它們移植性差,使用時佔用的服務器資源,排錯、維護不方便
最大的原因,不太建議把邏輯放在數據庫中
事務Transaction
InnoDB引擎,支持事務
事務,由若干條語句組成的,指的是要做的一系列操作
關係型數據庫中支持事務,必須支持其四個屬性(ACID):
特性 | 描述 |
---|---|
原子性(atomicity) | 一個事務是一個不可分割的工作單位,事務中包括的所有操作要麼全部做完,要麼什麼都不做 |
一致性(consistency) | 事務必須是使數據庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的 |
隔離性 (isolation) | 一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾 |
持久性(durability) | 持久性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響 |
- 原子性,要求事務中的所有操作,不可分割,不能做了一部分操作,還剩一部分操作
- 一致性,多個事務並行執行的結果,應該和事務排隊執行的結果一致。如果事務的並行執行和多線程讀寫共
- 享資源一樣不可預期,就不能保證一致性
- 隔離性,就是指多個事務訪問共同的數據了,應該互不干擾。隔離性,指的是究竟在一個事務處理期間,其他事務能不能訪問的問題
- 持久性,比較好理解,就是事務提交後,數據不能丟失
MySQL隔離級別
隔離性不好,事務的操作就會互相影響,帶來不同嚴重程度的後果
首先看看隔離性不好,帶來哪些問題:
- 更新丟失Lost Update
事務A和B,更新同一個數據,它們都讀取了初始值100,A要減10,B要加100,A減去10後更新爲90,B加100更新爲200,A的更新丟失了,就像從來沒有減過10一樣 - 髒讀
事務A和B,事務B讀取到了事務A未提交的數據(這個數據可能是一箇中間值,也可能事務A後來回滾事務)。事務A是否最後提交併不關心。只要讀取到了這個被修改的數據就是髒讀 - 不可重複讀Unrepeatable read
事務A在事務執行中相同查詢語句,得到了不同的結果,不能保證同一條查詢語句重複讀相同的結果就是不可以重複讀
例如,事務A查詢了一次後,事務B修改了數據,事務A又查詢了一次,發現數據不一致了
注意,髒讀講的是可以讀到相同的數據的,但是讀取的是一個未提交的數據,而不是提交的最終結果 - 幻讀Phantom read
事務A中同一個查詢要進行多次,事務B插入數據,導致A返回不同的結果集,如同幻覺,就是幻讀
數據集有記錄增加了,可以看做是增加了記錄的不可重複讀
有了上述問題,數據庫就必須要解決,提出了隔離級別
隔離級別由低到高,如下表
隔離級別 | 描述 |
---|---|
READ UNCOMMITTED | 讀取到未提交的數據 |
READ COMMITTED | 讀已經提交的數據,ORACLE默認隔離級別 |
REPEATABLE READ | 可以重複讀,MySQL的 默認隔離級別 |
SERIALIZABLE | 可串行化。事務間完全隔離,事務不能併發,只能串行執行 |
隔離級別越高,串行化越高,數據庫執行效率低;隔離級別越低,並行度越高,性能越高
隔離級別越高,當前事務處理的中間結果對其它事務不可見程度越高
-- 設置會話級或者全局隔離級別
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
-- 查詢隔離級別
SELECT @@global.tx_isolation;
SELECT @@tx_isolation;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 禁用自動提交
SET AUTOCOMMIT = 0
SERIALIZABLE,串行了,解決所有問題
REPEATABLE READ,事務A中同一條查詢語句返回同樣的結果,就是可以重複讀數據了。例如語句爲(select * from user)。解決的辦法有:
- 對select的數據加鎖,不允許其它事務刪除、修改的操作
- 第一次select的時候,對最後一次確切提交的事務的結果做快照
解決了不可以重複讀,但是有可能出現幻讀。因爲另一個事務可以增刪數據
READ COMMITTED,在事務中,每次select可以讀取到別的事務剛提交成功的新的數據。因爲讀到的是提交後的數據,解決了髒讀,但是不能解決 不可重複讀 和 幻讀 的問題。因爲其他事務前後修改了數據或增刪了數據
READ UNCOMMITTED,能讀取到別的事務還沒有提交的數據,完全沒有隔離性可言,出現了髒讀,當前其他問題
都可能出現
事務語法
START TRANSACTION或BEGIN開始一個事務,START TRANSACTION是標準SQL的語法
使用COMMIT提交事務後,變更成爲永久變更
ROLLBACK可以在提交事務之前,回滾變更,事務中的操作就如同沒有發生過一樣(原子性)
SET AUTOCOMMIT語句可以禁用或啓用默認的autocommit模式,用於當前連接。SET AUTOCOMMIT = 0 禁用自動提交事務。如果開啓自動提交,如果有一個修改表的語句執行後,會立即把更新存儲到磁盤
數據倉庫和數據庫的區別
本質上來說沒有區別,都是存放數據的地方, 但是數據庫關注數據的持久化、數據的關係,爲業務系統提供支持,事務支持;數據倉庫存儲數據的是爲了分析或者發掘而設計的表結構,可以存儲海量數據
數據庫存儲在線交易數據OLTP(聯機事務處理OLTP,On-line Transaction Processing);數據倉庫存儲歷史數據
用於分析OLAP(聯機分析處理OLAP,On-Line Analytical Processing)
數據庫支持在線業務,需要頻繁增刪改查;數據倉庫一般囤積歷史數據支持用於分析的SQL,一般不建議刪改
其他概念
遊標Cursor
操作查詢的結果集的一種方法
可以將遊標當做一個指針,指向結果集中的某一行