事務:一組原子性的SQL查詢,或者說一個獨立工作單元。
事務日誌:
在Oracle當中,被分解爲redo log、undo log,及所謂重做日誌和撤銷日誌
ACID測試:
A:atomicity,原子性;整個事務中的所有操作要麼全部成功執行,要麼全部失敗後回滾;
C:conststency,一致性;數據庫總是從一個一致性狀態轉換爲另一個一致性狀態;
I:Isolation,隔離性;一個事務所做出的操作在提交之前,是不能爲其它所見;
D:durability;持久性;一但事務提交,其所做的修改會永久保存於數據庫中;
隔離有多種隔離級別;
隔離級別越高,數據的安全性越高,不過它的併發能力就越低,隔離級別越低、併發性就越好,但是數據安全性差
事務:
啓動事務:start transaction
結束事務:
1、comit;提交
2、rollback;回滾
注意;只有事務型存儲引擎方能支持此類操作;
建議:顯示請求和提交事務,而不要使用“自動提交”功能;
autocommit={1|0}
示例:
關閉autocommit
MariaDB [hellodb]> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> show variables like '%auto%';
+--------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| autocommit | OFF |
+--------------------------------------+-------+
開始事務
MariaDB [hellodb]> start transaction;
刪除學生表裏面的stuid是18和23的學員
MariaDB [hellodb]> delete from students where stuid in (18,23);
執行rollback 回滾
MariaDB [hellodb]> rollback;
事務支持savepoint
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
savepoint示例:
# 開始事務
MariaDB [hellodb]> start transaction;
Query OK, 0 rows affected (0.00 sec)
# 先查看下最初的students表裏面的所有內容
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
# 執行delete語句刪除學員編號爲18的學員信息
MariaDB [hellodb]> delete from students where stuid=18;
Query OK, 1 row affected (0.00 sec)
# 創建一個事務還原點爲sp1
MariaDB [hellodb]> savepoint sp1;
Query OK, 0 rows affected (0.00 sec)
# 插入一條信息
MariaDB [hellodb]> insert into students (name,age,gender) values('Jinjiao King',100,'M');
Query OK, 1 row affected (0.00 sec)
# 創建一個事務還原點爲sp2
MariaDB [hellodb]> savepoint sp2;
Query OK, 0 rows affected (0.00 sec)
# 使用update語句更新13號學員的年齡
MariaDB [hellodb]> update students set age=43 where stuid=13;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 上述操作做完之後查看下錶是否發生變化
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 43 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 26 | Jinjiao King | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
# 對students操作完之後,假如說其中有數據有問題,然後回到之前創建的sp2上
MariaDB [hellodb]> rollback to sp2;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 26 | Jinjiao King | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
# 回滾到之前創建sp1的狀態上
MariaDB [hellodb]> rollback to sp1;
Query OK, 0 rows affected (0.00 sec)
# 全部回滾到最初狀態
MariaDB [hellodb]> rollback;
Query OK, 0 rows affected (0.00 sec)
事務隔離級別
事務隔離級別:
事務本身是需要隔離的,但隔離做的過於嚴格,任何一個事務都會阻塞其它訪問同一個資源的事務,爲了避免事務過多的影響其所謂的併發性,我們對事務關係型標準當中對事務的隔離等級做定義,每一種關係型數據庫,都可以設定自己到底支持哪種級別,大多數數據庫默認情況下都支持到第二種,但mysql支持第三級別
事務的四種隔離級別:(mysql默認是REPEATABLE READ 可重複讀)
READ UNCOMMITED (讀未提交)
髒讀、不可重複讀、幻讀
READ COMMITTED (讀提交)
不可重複讀、幻讀
REPEATABLE READ (可重讀)
幻讀
SERIALIZABILE (可串行化)
加鎖讀
可能存在問題:
髒讀: 讀別人未提交的數據
不可重複讀: 讀別人提交的數據也可以,但是別人提交以後產生一個問題查看的結果是之前看到的數據,看不到後面提交的新數據,不可重複讀,兩次讀到的數據是不一樣的
幻讀: 即讀取過程中,即使有其它提交的事務修改數據,仍只能讀取到未修改前的舊數據。
加鎖讀:
tx_isolation:服務器變量,默認爲REPEATABLE-READ;可在session級別進行修改
MVCC:多版本併發控制
死鎖:
兩個或多個事務在同一資源相互佔用,並請求鎖定對方佔用的資源的狀態;
數據庫爲了解決這樣的問題,設計了各種死鎖檢測、和死鎖超時時長
事務日誌:
事務日誌的寫入類型爲“追加”、因此其操作爲“順序IO”,此日誌通常也被稱爲“預寫式日誌(write ahead logging)”;
innodb_log_file_size
innodb_log_files_in_group
innodb_log_group_home_dir
事務的隔離級別示例:
髒讀實驗:
爲了實驗效果多開一個會話窗口,並且兩邊都把autocommit自動提交事務給關閉掉
MariaDB [hellodb]> set autocommit=0;
MariaDB [hellodb]> show variables like '%auto%';
+------------------------------+-------+
| Variable_name | Value |
+------------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| autocommit | OFF |
+------------------------------+-------+
1、把兩個會話改爲READ-UNCOMMITTED模式;
MariaDB [hellodb]> show global variables like '%isola%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
MariaDB [hellodb]> set tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected (0.00 sec)
在兩個會話上都啓用事務
MariaDB [hellodb]> start transaction;
Query OK, 0 rows affected (0.00 sec)
在第一個會話中修改students表裏面的13號學員的年齡爲40
MariaDB [hellodb]> update students set age=40 where stuid=13;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [hellodb]> select * from students where stuid=13;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 13 | Tian Boguang | 40 | M | 2 | NULL |
+-------+--------------+-----+--------+---------+-----------+
1 row in set (0.00 sec)
然後在第二個會話裏面查看是不是能看到13號學員的修改後的數據庫此時第一個窗口並未提交事務
MariaDB [hellodb]> select * from students where stuid=13;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 13 | Tian Boguang | 40 | M | 2 | NULL |
+-------+--------------+-----+--------+---------+-----------+
1 row in set (0.00 sec)
----------------------------------------------------------------------------------------
REPEATABLE-READ模式:
設置爲REPEATABLE-READ
MariaDB [hellodb]> set tx_isolation='REPEATABLE-READ';
Query OK, 0 rows affected (0.00 sec)
刪除stuid爲3的學員
MariaDB [hellodb]> delete from students where stuid=3;
Query OK, 1 row affected (0.00 sec)
在第一會話提交事務
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.00 sec)
在第一會話查詢stuid爲3的已經查不到了
MariaDB [hellodb]> select * from students where stuid=3;
Empty set (0.00 sec)
在第二個會話中查詢還是可以查詢到,這就產生了幻讀,這種模式解決了不可重複讀,不過還是避免不了幻讀的問題
MariaDB [hellodb]> select * from students where stuid = 3;
+-------+-----------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-----------+-----+--------+---------+-----------+
| 3 | Xie Yanke | 53 | M | 2 | 16 |
+-------+-----------+-----+--------+---------+-----------+
1 row in set (0.00 sec)
只有在第二會話中執行提交事務之後再次查詢就沒有出現了
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> select * from students where stuid=3;
Empty set (0.00 sec)
----------------------------------------------------------------------------------
SERIALIZABLE 加鎖讀示例:
1、設置模式爲SERIALIZABLE
MariaDB [hellodb]> set tx_isolation='SERIALIZABLE';
Query OK, 0 rows affected (0.00 sec)
2、修改stuid爲14的年齡
MariaDB [hellodb]> update students set age=21 where stuid=14;
3、在本窗口查詢修改結果
MariaDB [hellodb]> select * from students where stuid=14;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 14 | Lu Wushuang | 21 | F | 3 | NULL |
+-------+-------------+-----+--------+---------+-----------+
4、在第二個會話窗口查詢,只要執行查詢之後就會被阻塞,然後過了一定時長系統會提示超時
MariaDB [hellodb]> select * from students;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
5、第一窗口執行提交事務
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.02 sec)
6、再在第二窗口查詢,就可以查詢
MariaDB [hellodb]> select * from students where stuid=14;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 14 | Lu Wushuang | 21 | F | 3 | NULL |
+-------+-------------+-----+--------+---------+-----------+
1 row in set (0.00 sec)