對於事務而言,它須要知足ACID特性,下面就簡要的說說事務的ACID特性。sql
A,表示原子性;原子性指整個數據庫事務是不可分割的工做單位。只有使事務中全部的數據庫操做都執行成功,整個事務的執行纔算成功。事務中任何一個sql語句執行失敗,那麼已經執行成功的sql語句也必須撤銷,數據庫狀態應該退回到執行事務前的狀態;
C,表示一致性;也就是說一致性指事務將數據庫從一種狀態轉變爲另外一種一致的狀態,在事務開始以前和事務結束之後,數據庫的完整性約束沒有被破壞;
I,表示隔離性;隔離性也叫作併發控制、可串行化或者鎖。事務的隔離性要求每一個讀寫事務的對象與其它事務的操做對象能相互分離,即該事務提交前對其它事務都不可見,這一般使用鎖來實現;
D,持久性,表示事務一旦提交了,其結果就是永久性的,也就是數據就已經寫入到數據庫了,若是發生了宕機等事故,數據庫也能將數據恢復。數據庫
理論總結的再好,終歸都要經過實踐來進行理解。下面就來講說MySQL中是如何使用事務的。session
在MySQL命令行的默認設置下,事務都是自動提交的,即執行SQL語句後就會立刻執行COMMIT操做。所以要顯示地開啓一個事務須使用命令BEGIN或START TRANSACTION,或者執行命令SET AUTOCOMMIT=0,用來禁止使用當前會話的自動提交。架構
來看看咱們可使用哪些事務控制語句。併發
BEGIN或START TRANSACTION;顯示地開啓一個事務;ide
COMMIT;也可使用COMMIT WORK,不過兩者是等價的。COMMIT會提交事務,並使已對數據庫進行的全部修改稱爲永久性的;測試
ROLLBACK;有可使用ROLLBACK WORK,不過兩者是等價的。回滾會結束用戶的事務,並撤銷正在進行的全部未提交的修改;spa
SAVEPOINT identifier;SAVEPOINT容許在事務中建立一個保存點,一個事務中能夠有多個SAVEPOINT;命令行
RELEASE SAVEPOINT identifier;刪除一個事務的保存點,當沒有指定的保存點時,執行該語句會拋出一個異常;code
ROLLBACK TO identifier;把事務回滾到標記點;
SET TRANSACTION;用來設置事務的隔離級別。InnoDB存儲引擎提供事務的隔離級別有 READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
注意:默認的行爲(不帶session和global)是爲下一個(未開始)事務設置隔離級別。
若是使用GLOBAL關鍵字,語句在全局對從那點開始建立的全部新鏈接(除了不存在的鏈接)設置默認事務級別。你須要SUPER權限來作這個。
使用SESSION 關鍵字爲未來在當前鏈接上執行的事務設置默認事務級別。 任何客戶端都能自由改變會話隔離級別(甚至在事務的中間),或者爲下一個事務設置隔離級別。
有的時候有些SQL語句會產生一個隱式的提交操做,即執行完成這些語句後,會有一個隱式的COMMIT操做。有如下SQL語句,不用你去「管」:
DDL語句,ALTER DATABASE、ALTER EVENT、ALTER PROCEDURE、ALTER TABLE、ALTER VIEW、CREATE TABLE、DROP TABLE、RENAME TABLE、TRUNCATE TABLE等;
修改MYSQL架構的語句,CREATE USER、DROP USER、GRANT、RENAME USER、REVOKE、SET PASSWORD;
管理語句,ANALYZE TABLE、CACHE INDEX、CHECK TABLE、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE等。
以上的這些SQL操做都是隱式的提交操做,不須要手動顯式提交。
-- 查詢全局事務
SELECT @@global.tx_isolation;
-- 查詢會話事務
SELECT @@session.tx_isolation;
-- 或者使用
SELECT @@tx_isolation;
-- 設置全局事務
set global transaction isolation level read committed;
-- 設置會話事務
set session transaction isolation level read committed;
-- 設置下一個操做的事務
set transaction isolation level repeatable read;
SELECT @@autocommit;
-- 默認爲1 即自動提交,0手動提交
SET autocommit = 1;
-- 若是沒有設置事務提交方式爲手動提交,那麼須要顯示聲明一個開啓事務的操做
START TRANSACTION; -- 或者 BEGIN;
-- 執行操做語句
INSERT INTO t_hwp_test(user_id,user_name)VALUES(6,'superAdmin');
-- 設置一個保存點,事務能夠回滾到指定保存點處,那麼在此節點以前的操做將會有效
SAVEPOINT tx;
-- 執行操做(若是這裏這條語句發生錯誤,那麼腳本執行就結束了,下面的語句不會繼續執行,數據庫也不會給你自動回滾,該事務也尚未提交,只能執行腳本手動回滾事務)
INSERT INTO t_hwp_test(user_id,user_name)VALUES(4,'superAdmin');
-- 手動回滾到指定保存點處
ROLLBACK TO tx;
-- 最後提交,不然有可能其餘鏈接看不到你未提交的值
COMMIT;
若是在上面的操做語句中發生了錯誤,不要期盼數據庫會給你自動回滾,而是在那兒就會中止執行,事務若是尚未提交,須要手動回滾。
1)內部使用事務支持
也就是在存儲過程內部聲明事務開啓與提交,這樣的壞處就是,你沒法回滾這些已經提交了的事務!
2)外部使用事務支持
也就是在調用存儲過程的先後加一個事務控制,好處就是存儲過程執行的操做並無真正提交,等到執行了 COMMIT纔會提交。
-- 若是存在刪除調用存儲過程 DROP PROCEDURE IF EXISTS sp_call_jobs; -- 建立調用存儲過程 CREATE PROCEDURE sp_call_jobs() BEGIN DECLARE _row, _err, _count INT DEFAULT 0; -- 遇到錯誤繼續往下執行,相似於 try-catch DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND SET _err = 1; WHILE _row < 3 DO -- START TRANSACTION; 在裏面開啓事務 INSERT INTO t_hwp_test(user_id,user_name,user_status,user_type,relative_id,account_id,user_unit,user_update_time) VALUES(19,'測試1112',1,7,2,2,'系統','2016-01-07 16:39:36'); --COMMIT; 提交事務 IF _err = 1 THEN SET _count = _count + 1; END IF; SET _row = _row + 1; END WHILE; SELECT _count; END; -- 使用外部事務的方式調用存儲過程 START TRANSACTION; CALL sp_call_jobs(); COMMIT;