MySQL事務

事務:一組原子性的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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章