1. 程式人生 > >mysql資料庫的隔離性

mysql資料庫的隔離性

程式碼review的時候看到同事把業務鎖(insertDelete實現)和業務操作放在一個事務裡。

程式碼結構如下:

transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
   bizLockRepoImpl.insert(biz_id,id);//其中biz_id是主鍵
   xxxxx;
   xxxxx;
   xxxxx;
   ……………;
   bizLockRepoImpl.delete(biz_id,id);//其中biz_id是主鍵
});

頓感十分奇怪,這樣根據『事務隔離性』的原則,豈不是等於沒有做併發控制麼?於是,立馬安裝了個mysql進行驗證。實驗如下,注意時序性:

實驗一:

      目的:

      證明,雖然第一個事務還沒提交,但是如果其他事務裡的sql涉及到和執行中的事務有主鍵衝突或者update了相同行的時候,其他的事務也是不能正常提交的。

      原因:在MVCC控制中,寫操作是『當前讀』,讀取記錄的最新版本。並且,讀取之後,還需要保證其他併發事務不能修改當前記錄,對讀取記錄加鎖。

      步驟:

     1. 開啟一個mysql終端:

    2. 開啟另外一個mysql終端:

mysql> insert into biz_lock vaules(8,8,now(),now());
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

     輸出insert語句,就掛住了。等待了一段時間之後(一直不要去commit第一個事務),報錯如上。『等鎖超時』。

     結論:

     雖然我們知道資料庫具有隔離性『定義:當多個使用者併發訪問資料庫時,比如操作同一張表時,資料庫為每一個使用者開啟的事務,不能被其他事務的操作所幹擾,多個併發事務之間要相互隔離。』。資料庫引擎在事務commit前,也是會進行一些保護(因為資料庫引擎是怎麼實現的還沒有去研究,先把表象說明白)。

實驗二:

      目的,看看我們所理解的資料庫事務的『隔離性』.

     1. 客戶端一:    

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into biz_lock values(9,9,now(),now());
Query OK, 1 row affected (0.00 sec)

mysql> select * from biz_lock where biz_id = 9;
+------+--------+---------------------+---------------------+
| id   | biz_id | gmt_create          | gmt_modified        |
+------+--------+---------------------+---------------------+
| 9    | 9      | 2018-01-09 19:36:47 | 2018-01-09 19:36:47 |
+------+--------+---------------------+---------------------+
1 row in set (0.00 sec)

    在一個事務裡insert了一條記錄,在這個事務裡select是可以看到的。

    2. 客戶端二:

mysql> select * from biz_lock where biz_id = 9;
Empty set (0.00 sec)

    3. 客戶端一:

mysql> commit work;
Query OK, 0 rows affected (0.00 sec)

    4. 客戶端二:

mysql> select * from biz_lock where biz_id = 9;
+------+--------+---------------------+---------------------+
| id   | biz_id | gmt_create          | gmt_modified        |
+------+--------+---------------------+---------------------+
| 9    | 9      | 2018-01-09 19:36:47 | 2018-01-09 19:36:47 |
+------+--------+---------------------+---------------------+
1 row in set (0.00 sec)

    結論:我們看到,在事務一提交前,如果我們在其他的客戶端(即其他事務裡)查詢是看不到事務一里還沒有commit的資料的。即我們討論的事務隔離性。