1. 程式人生 > 實用技巧 >MySql的回顧十:TCL與事務的展示

MySql的回顧十:TCL與事務的展示

  山隨宴坐圖畫出,水作夜窗風雨來。觀水觀山皆得妙,更將何物汙靈臺。經過風雨的洗禮,對面山上的樹,路兩旁的花草更加的鮮豔動人,路邊的樹又抽出新的枝芽,樹下還有幾朵菌類上的雨露顯得熠熠動人,就是天氣有幾許絲涼。各位看官注意新增衣物。

  今天繼續有我帶領讀者們繼續學習MySql的TCL語言,廢話不多說直接上概念!衝呀...

Transaction Control Language 事物控制語言
事物:一個或一組SQL語句中組成一個執行單元,這個執行單元要麼全部執行,要麼全部不執行。每個SQL語句是相互依賴的。
而整個單獨單元作為一個不可分割的整體,如果單元中某條SQL語句一旦執行失敗或產生錯誤,整個單元將會回滾。
所有受到影響的資料將返回到事物開始以前的狀態;如果單元中所有的SQL語句均執行成功,則事物被順利執行。 儲存引擎(表型別)引入
1.概念:在MySql中的資料用各種不同的技術儲存在檔案(或記憶體)中。 2.通過SHOW ENGINES;嗯爭斯來檢視MySql支援的儲存引擎。 3.在MySql中用的最多的儲存引擎有INNODB,MYISAM,MEMORY等,其中INNODB支援事物,而MYISAM,MEMORY等不支援事物。 事物的ACID屬性 1.原子性(Atomicity)原子性是指事物是一個不可分割的工作單位,事物中的操作要麼都發生,要麼都不發生。 2.一致性(Consistency)事物必須使資料庫從一個一致性狀態變換到另一個一致性狀態。
3.隔離性(Isolation)事物的隔離性是指一個事物的執行不能被其他事物干擾,即一個事物 內部的操作及使用的資料對併發的其他事物是隔離的,併發執行的各個之間不能互相干擾。 4.永續性(Durability)永續性是指一個事物一旦被提交,它對資料庫中資料改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響。 案例:轉賬,虛擬碼。喜羊羊準備給灰太狼轉500讓灰太狼協助羊村的圍欄修復。 喜羊羊 1000 灰太狼 1000 UPDATE 表 SET 喜羊羊的餘額=500 WHERE name='喜羊羊' 意外斷開了,喜羊羊少了500,灰太狼該正常走以下程式碼。 UPDATE 表 SET 灰太狼的餘額
=1500 WHERE name='灰太狼'

檢視引擎
SHOW ENGINES;

事務的建立

隱式事務: 事務沒有明顯的開啟和結束的標記
比如INSERT,UPDATE,DALETE語句
DELETE FROM 表 WHERE id=1;

顯示事務:事務具有明顯的開啟和結束的標記
前提:必須先設定自動提交功能為禁用
SET autocommit=0;

步驟1:開啟事物
SET autocommit=0;
start transcommit=0;
start transaction;可選的
步驟2:
編寫事務中的SQL語句(SELECT INSERT UPDATE DELETE) 語句1; 語句2; ... 步驟3:結束事物 commit;提交事務 rollback;回滾事務 刪除表 DROP TABLE IF EXISTS accoun_t; 建立表 CREATE TABLE accoun_t( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(20), balance DOUBLE ); 插入測試資料 INSERT INTO accoun_t(username,balance) VALUES('喜羊羊',1000),('灰太狼',1000); #演示事務的使用步驟:提交 #開啟事務 SET autocommit=0; START TRANSACTION; #模擬編寫一組事務 UPDATE accoun_t SET balance = 500 WHERE username="喜羊羊"; UPDATE accoun_t SET balance = 1500 WHERE username="灰太狼"; #結束事務:提交 COMMIT; #查看錶資料 SELECT * FROM accoun_t;

#演示事務的使用步驟:回滾
#開啟事務
SET autocommit=0;
START TRANSACTION;
#模擬編寫一組事務
UPDATE accoun_t SET balance = 1000 WHERE username="喜羊羊";
UPDATE accoun_t SET balance = 1000 WHERE username="灰太狼";

#結束事務回滾
ROLLBACK;
#查看錶資料
SELECT * FROM accoun_t;

#沒有變回1000

事務的原理

#事務的併發介紹
#對於同時執行的多個事務,當這些事務訪問資料庫中相同的資料時,如果沒有采取必要的隔離機制,就會導致各種併發問題:
髒讀:一個事物讀取到另一個事物中尚未提交的資料。(沒有被提交)
例:對於兩個事務T1,T2.T1讀取了已經被T2更新但還沒有被提交的欄位,之後若T2回滾,T1讀取的內容就是臨時且無效的。

不可重複讀:一個事物中兩次讀取資料內容不一致,要求的是一個事務中多次讀取資料是一致的,這是事物UPDATE時引發的問題。(更新)
例:對於兩個事物T1,T2。T1讀取了一個欄位,然後T2更新了該欄位之後,T1再次讀取同一個欄位,值就不同了。

幻讀:一個事務中兩次讀取的資料的數量不一致,要求在一個事務多次讀取的資料的數量是一致的,這是INSERT或者DELETE時引發的問題。(插入)
例:對於兩個事物T1,T2。T1從一個表中讀取了一個欄位,然後T2在該表中插入了一些新的行。之後如果T1再次讀取同一個表,就會多出幾行。

事務的隔離級別

讀未提交:允許事物讀取未被其他事務提交的變更,髒讀,不可重複讀和幻讀都會出現。
讀已提交:只允許事務讀取已經被其他事物提交的變更,可避免髒讀,但不可重複讀和幻讀問題任然可能出現。
可重複讀:確保事務可以多次從一個欄位中讀取相同的值,在這個事務持續期間,禁止其他事務對這個欄位進行更新。
序列化:確保事務可以從一個表讀取相同的行,在這個事務持續期間,禁止其他事務對該表執行插入,更新和刪除操作,所有併發問題都可以避免,但效能十分低下。
每啟動一個mysql程式,就會獲得一個單獨的資料庫連線,每個資料庫連線都有一個。
全域性變數@@tx_isolation,表示當前事務隔離級別。
檢視當前的隔離級別:SELECT @@tx_isolation;
設定當前MySql連線的隔離級別
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
設定資料庫系統的全域性的隔離級別:
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;

#資料庫事務的隔離性:資料庫系統必須具有隔離性併發執行各個事務的能力,使它們不會相互影響,避免各種併發問題。
#一個事務與其他事務隔離的程度稱為隔離級別。
#ORACLE:支援的2種事務隔離級別:READ COMMITED,SERIALIZABLE。ORACLE預設的事物隔離級別為:READ COMMITED。
#MySql支援4種事務隔離級別,Mysql預設的事物隔離級別為:REPEATABLE READ

髒讀的演示

以下操作轉入CMD或者LINUX下操作
檢視預設的隔離級別
SELECT @@tx_isolation;

T1切換庫
設定隔離級別
開啟事務
查看錶資料
USE girls;
set global transaction isolation level read uncommitted;
start transaction;

T2切換庫
設定隔離級別
開啟事務
查看錶資料
USE girls;
set global transaction isolation level read uncommitted;
start transaction;
SELECT * FROM accoun_t;

T1修改資料
回滾
UPDATE accoun_t SET username='xiyangyang' WHERE id=1;
rollback;

髒讀問題解決:
先把資料恢復
UPDATE accoun_t SET balance=500 WHERE id=1;
UPDATE accoun_t SET balance=1500 WHERE id=2;

T1設定隔離級別
set global transaction isolation level read committed;
start transaction;

T2退出重新進入
開啟事務
切換庫
mysql -u RemoteLogin -p
start transaction;
USE girls;

T1修改資料,不提交
UPDATE accoun_t SET balance=500 WHERE id=1;
UPDATE accoun_t SET balance=1500 WHERE id=2;

T2查詢,未查到已修改的資料

T1進行提交

T2查到資料

不可重複讀演示

T1先恢復資料
設定隔離級別
UPDATE accoun_t SET balance=1000 WHERE id=1;
SET global transaction isolation level read committed;

T2登陸資料庫
切換庫
開啟事物
檢視資料
mysql -u RemoteLogin -p
USE girls;
start transaction;
SELECT * FROM accoun_t;

T1開啟事物
修改資料
提交資料
start transaction;
UPDATE accoun_t SET balance=1500 WHERE id=1;
commit;

T2查詢發現與第一次查詢到的資料不一致

解決方法
T1提升隔離級別
set global transaction isolation level repeatable READ;

T2重新登陸
開啟事務
檢視資料
mysql -u RemoteLogin -p
start transaction;
SELECT * FROM girls.accoun_t;

T1開啟事務
修改資料
提交資料
start transaction;
UPDATE accoun_t SET balance=1300 WHERE id=1;
commit;

T2檢視還是原來資料

如果想看最新資料,先提交再檢視。

幻讀演示
T1關閉事務
切換庫
檢視資料
SET autocommit=0;
USE girls;
SELECT * FROM accoun_t;

T2關閉事物
切換庫
檢視資料
新插入一行
提交
SET autocommit=0;
USE girls;
SELECT * FROM accoun_t;
INSERT INTO accoun_t values(NULL,'shiyuan',2000);
commit;

T1修改資料,結果顯示改了四行。

解決方法序列化
T1提高事務等級序列化
關閉事物
檢視資料
更新資料但不執行
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET autocommit=0;
SELECT * FROM accoun_t;
UPDATE accoun_t SET username='dayitong';   #先不執行

問題解決
T2開啟事物序列化
關閉事物
插入一行資料
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET autocommit=0;
INSERT INTO accoun_t VALUES(NULL,'yazhou',5000);

T1執行修改資料
提交
UPDATE accoun_t SET username='dayitong';
commit;

T2等待超時被踢出

回滾點
關閉事務
切換庫
檢視資料
SET autocommit=0;
USE girls;
SELECT * FROM accoun_t;

把username全部改成喜羊羊
把username全部改成灰太狼
設定回滾點
再把username全部改成光頭強
資料回檔至存檔
檢視資料
UPDATE accoun_t SET username='喜羊羊';
UPDATE accoun_t SET username='灰太狼';
SAVEPOINT cundang;
UPDATE accoun_t SET username='光頭強';
ROLLBACK TO cundang;
SELECT * FROM accoun_t;

DELETETRUNCATE在事物中的區別

#演示DELETE
關閉事務自動提交
開啟事務
刪除表
回滾
檢視
SET autocommit=0;
START TRANSACTION;
DELETE FROM major2;
ROLLBACK;
SELECT * FROM major2;

#演示TRUNCATE
關閉事務的自動提交
開啟事物
刪除表
回滾
檢視
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE major2;
ROLLBACK;
SELECT * FROM major2;

  事務控制到此結束,希望看到這裡的讀者們有收穫。咱們不見不散下次再見!o(^▽^)o