標籤:mysql 事物
一、什麼是事物?
個人理解,sql中的事物就是給sql語句做一個分組,組內的sql語句要不然就全部執行成功,要不然就完全的不會執。或者說作為單個邏輯工作單元執行的一系列操作,要麼完全地執行,要麼完全地不執行。
交易處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向資料的資源。通過將一組相關操作組合為一個要麼全部成功要麼全部失敗的單元,可以簡化錯誤恢複並使應用程式更加可靠。一個邏輯工作單元要成為事務。
二、關於事物的樣本,以及如何在mysql中開啟事物。
start transaction;開啟事務
Rollback 復原事務,即撤銷指定的sql語句(只能回退insert delete update語句),復原到上一次commit的位置.
Commit 提交事務,提交未儲存的事務.
savepoint 保留點 ,交易處理中設定的臨時預留位置 你可以對它發布回退(與整個交易回復不同).(也可以理解為回退到某個點,並不會完全回退到上次commit的位置。)
樣本:
create table test2(id int PRIMARY KEY auto_increment,name VARCHAR(20)) engine=innodb;
INSERT INTO test2(name) VALUE ("user1"),("user2"),("user3");
start transaction; #建立事物。
insert into test2 (name)values(‘user4‘);
select * from test2;
commit; #提交後,真正的把資料寫到資料庫中。
-------------------------下面是關於保留點的樣本-------------------------------
start transaction;
insert into test2 (name)values(‘wu‘);
savepoint insert_wu; #定義一個保留點
select * from test2;
delete from test2 where id=4;
savepoint delete1; #定義一個保留點
select * from test2;
delete from test2 where id=1;
savepoint delete2; #定義一個保留點
select * from test2;
rollback to delete1; #復原到哪個保留點之後。
select * from test2;
python中調用資料庫啟動事務的方式:
import pymysql
#添加資料
conn = pymysql.connect(host=‘127.0.0.1‘, port=3306, user=‘root‘, passwd=‘‘, db=‘yyy‘)
cursor = conn.cursor()
try:
insertSQL0="INSERT INTO ACCOUNT2 (name,balance) VALUES (‘user1‘,4000)"
insertSQL1="UPDATE account2 set balance=balance-30 WHERE name=‘user2‘"
insertSQL2="UPDATE account2 set balance=balance+30 WHERE name=‘user3"
cursor = conn.cursor()
cursor.execute(insertSQL0)
conn.commit()
cursor.execute(insertSQL1)
raise Exception #觸發異常,用來類比第三條sql語句執行異常。
cursor.execute(insertSQL2)
cursor.close()
conn.commit()
except Exception as e:
conn.rollback()
conn.commit()
cursor.close()
conn.close()
三、事物特性的總結:
原子性:
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
隔離性:
事務的隔離性是指多個使用者並發訪問資料庫時,一個使用者的事務不能被其它使用者的事務所幹擾,多個並發事務之間資料要相互隔離。
永久性:
事物一旦被提交,它對資料庫中資料的改變就是永久性的。
事物的隔離性是非常重要的!!如果不考慮隔離性會出現以下問題。
髒讀(讀取髒資料)
髒讀就是一個事物讀取到了另外一個事物還沒有提交的資料,這種情況在生產環境特別危險!!
假如說,現在事物1正在修改某一個資料,並且準備提交(還沒有提交!),此時,事物2讀取到了同一資料之後,事物1由於執行了某條sql語句沒成功,突然復原,此時的事物1已經把修改過的資料,變回了原來的值,事物2所讀到的,是事物1之前修改過還沒提交的資料,所以說,事物2所讀到的資料和資料庫中的資料根本不一致!!所以是不正確的資料。
關於髒讀的樣本:
a 1000
b 1000
a:
start transaction;
update set money=money+100 where name=b;
b:
start transaction;
select * from account where name=b;--1100
commit;
a:
rollback;
b: start transaction;
select * from account where name=b;--1000
2.不可重複讀取:
事物1讀取了資料庫中的資料後,事物2對這個資料進行了更新操作,導致事物1無法讀取前一次的結果。
說的再簡單一些,就是在一個事物內讀取表中的某一行記錄,多次讀取的內容是不同的。
事務1讀取某一資料後,事物2對其做了修改,當事物1再次讀該資料後,得到與前一不同的值。
3.產生幽靈資料:
是指在一個事務內讀取到了別的事務插入的資料,導致前後讀取不一致。(一個事務讀取到了另一個事務已經提交的資料—增加記錄、刪除記錄),在某寫情況下並不是問題,在另一些情況下就是問題。
b 1000
c 2000
d 3000
a:
start transaction
select sum(money) from account;---3000 3000
-------------------
d:start transaction;
insert into account values(d,3000);
commit;
-------------------
select count(*)from account;---3 3
3000/3 = 1000 1000
避免以上幾種情況發生的隔離等級:
四個隔離等級:
Serializable:可避免髒讀、不可重複讀取、虛讀情況的發生。(序列化)
Repeatable read:可避免髒讀、不可重複讀取情況的發生。(可重複讀)不可以避免虛讀
Read committed:可避免髒讀情況發生(讀已提交)
Read uncommitted:最低層級,以上情況均無法保證。(讀未提交)
安全性考慮:Serializable>Repeatable read>Read committed>Read uncommitted
資料庫效率:Read uncommitted>Read committed>Repeatable read>Serializable
一般情況下,我們會使用Repeatable read、Read committed mysql資料庫預設的資料庫隔離等級Repeatable read
mysql中設定資料庫的隔離等級語句:
set [global/session] transaction isolation level xxxx;
如果使用global則修改的是資料庫的預設隔離等級,所有新開的視窗的隔離等級繼承自這個預設隔離等級如果使用session修改,則修改的是當前用戶端的隔離等級,和資料庫預設隔離等級無關。當前的用戶端是什麼隔離等級,就能防止什麼隔離等級問題,和其他用戶端是什麼隔離等級無關。
mysql中設定資料庫的隔離等級語句:
select @@tx_isolation;
本文出自 “reBiRTH” 部落格,請務必保留此出處http://suhaozhi.blog.51cto.com/7272298/1934310
12.關於mysql事物。