Home | Mirror | Search

7. 事務處理和鎖定語句

Transactional and Locking Statements

開始事務 begin、start transaction 或者 set autocommit=0

事務的特徵:原子性(Atomiocity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability),這四個特性簡稱ACID特性。
    原子性:事務是資料庫的邏輯工作單位,事務中包括的所有操作要麼都做,要麼都不做。
    一致性:事務執行的結果必須是使資料庫從一個一致性的狀態變到另外一個一致性狀態。
    隔離性:一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對其他事務是隔離的,並發執行的各個事務之間互相不干擾。
    持久性:一個事務一旦成功提交,對資料庫中數據的修改就是持久性的。接下來其他的其他操作或故障不應該對其執行結果有任何影響。
	

事務隔離模式

 	1) READ UNCOMMITED
    SELECT的時候允許臟讀,即SELECT會讀取其他事務修改而還沒有提交的數據。

    2)READ COMMITED
    SELECT的時候無法重複讀,即同一個事務中兩次執行同樣的查詢語句,若在第一次與第二次查詢之間時間段,其他事務又剛好修改了其查詢的數據且提交了,則兩次讀到的數據不一致。

    3) REPEATABLE READ
    SELECT的時候可以重複讀,即同一個事務中兩次執行同樣的查詢語句,得到的數據始終都是一致的。實現的原理是,在一個事務對數據行執行讀取或寫入操作時鎖定了這些數據行。
    但是這種方式又引發了幻想讀的問題。因為只能鎖定讀取或寫入的行,不能阻止另一個事務插入數據,後期執行同樣的查詢會產生更多的結果。

    4)SERIALIZABLE
    與可重複讀的唯一區別是,預設把普通的SELECT語句改成SELECT …. LOCK IN SHARE MODE。即為查詢語句涉及到的數據加上共享瑣,阻塞其他事務修改真實數據。
    serializable模式中,事務被強製為依次執行。這是SQL標準建議的預設行為。

  查看InnoDB系統級別的事務隔離級別:mysql> SELECT @@global.tx_isolation;
  查看InnoDB會話級別的事務隔離級別:mysql> SELECT @@tx_isolation;
  修改InnoDB系統級別的事務隔離級別:mysql> set global transaction isolation level read committed;
  修改InnoDB會話級別的事務隔離級別:mysql> set session transaction isolation level read committed;
	

鎖機制

    1) 共享鎖:由讀表操作加上的鎖,加鎖後其他用戶只能獲取該表或行的共享鎖,不能獲取排它鎖,也就是說只能讀不能寫
    2) 排它鎖:由寫表操作加上的鎖,加鎖後其他用戶不能獲取該表或行的任何鎖,典型是mysql事務中的

    鎖的範圍:
    行鎖: 對某行記錄加上鎖
    表鎖: 對整個表加上鎖
	

共享鎖(share mode), 排他鎖(for update)

7.1. 排他鎖

下面做作一個實驗,驗證鎖的效果

終端一,首先進入事務狀態然後運行下面語句

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

mysql> select * from t1 where id='3' for update;
+----+--------+---------------------+---------------------+
| id | name   | ctime               | mtime               |
+----+--------+---------------------+---------------------+
|  3 | test   | 0000-00-00 00:00:00 | 2013-01-14 13:05:41 |
+----+--------+---------------------+---------------------+
1 row in set (0.00 sec)
		
		

終端二, 查詢表中數據

		
mysql> select * from t1;
+----+--------+---------------------+---------------------+
| id | name   | ctime               | mtime               |
+----+--------+---------------------+---------------------+
|  1 | neo    | 0000-00-00 00:00:00 | 2013-01-14 13:00:00 |
|  2 | zen    | 0000-00-00 00:00:00 | 2013-01-14 13:00:43 |
|  3 | test   | 0000-00-00 00:00:00 | 2013-01-14 13:05:41 |
+----+--------+---------------------+---------------------+
3 rows in set (0.00 sec)
		
		

增加“for update”查詢非鎖定記錄

		
mysql> select * from t1 where id=2 for update;
+----+------+---------------------+---------------------+
| id | name | ctime               | mtime               |
+----+------+---------------------+---------------------+
|  2 | zen  | 0000-00-00 00:00:00 | 2013-01-14 13:00:43 |
+----+------+---------------------+---------------------+
1 row in set (0.00 sec)
		
		

查詢被鎖定記錄

		
mysql> select * from t1 where id=3 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
		
		

查詢所有記錄,因為記錄中包含了id=3那條,所以也不允許查詢。

		
mysql> select * from t1 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
		
		

測試修改記錄

		
mysql> UPDATE `t1` SET `name`='testaa' WHERE  `id`=3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
		
		

提示

在沒有出現ERROR 1205 (HY000)的這段時間,只要終端一中執行commit,rollback鎖就釋放了.終端二中的語句就會運行。

select trx_query from information_schema.innodb_trx; 可以查看被鎖的SQL語句

7.2. 表的加鎖與解鎖

LOCK TABLES tablename WRITE;
LOCK TABLES tablename READ;

...
...

UNLOCK TABLES;
		

7.3. 事務所用到的表

information_schema

		
select * from innodb_trx;
select * from innodb_lock_waits;
select * from innodb_locks;
		
		
comments powered by Disqus