1、多個線程同時修改數據,存在數據不一致的情況,也就是並發控制的問題。
2、mysql提供讀鎖和寫鎖,讀鎖之上可以再加讀鎖,不能加寫鎖,而寫鎖之上不能加任何鎖。也就是說,讀鎖是共享的,寫鎖是排他的。
3、鎖粒度,為了更好的並發控制,鎖的粒度應該盡可能小,也就是只鎖定修改的數據。但是,鎖本身也有一定的開銷,包括獲取鎖,檢查鎖是否釋放,釋放鎖,這些操作也耗費一定的資源。鎖的粒度小,在並發控制的時候,也就意味着需要更多的鎖,鎖的總開銷也就越大。
4、根據鎖的粒度,分為表鎖和行鎖,mysql本身使用表鎖來實現不同的目的,比如alter table,這個時候會忽略存儲引擎的鎖機制。存儲引擎支持表鎖和行鎖,不同存儲引擎的實現不同。
5、特別注意:mysql支持不同的事務隔離級別,隔離級別越高,鎖的粒度越大,也就是鎖的內容越多。比如:
考慮下面的情況,A,B客戶端的事務隔離級別都是read-uncommitted, 鎖的粒度是行鎖。
步驟一、A執行start transaction,修改一條記錄
步驟二、B執行start transaction,修改另一條記錄
二者是不阻塞的,證明read-uncommitted 是行鎖。同理,可以證明read-committed是行鎖,repeatable-read和serializable是表鎖。
注意:加什么鎖,鎖多大范圍,和很多因素有關,包括是否有索引,執行的操作等。比如上面的情況,A、B都是repeatable-read,A進行select,B進行update不阻塞。但是A進行update,B進行update就會阻塞。
6、死鎖,mysql在事務中,InnoDB會根據事務隔離級別自動鎖定,而釋放實在事務commit或者rollback的時候才釋放。這就會存在死鎖的情況,考慮下面的情況:
A,B客戶端的事務隔離級別都是read-uncommitted, 鎖的粒度是行鎖。
步驟一、A執行start transaction,修改記錄1
步驟二、B執行start transaction,修改記錄2
步驟三、A修改記錄2
步驟四、B修改記錄1
出現死鎖,不過mysql功能很強大,可以檢測出這種死鎖,B修改記錄1的時候報錯 ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting trans
action