Home | Mirror | Search |
開始事務 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)
下面做作一個實驗,驗證鎖的效果
終端一,首先進入事務狀態然後運行下面語句
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語句