首頁 >資料庫 >mysql教程 >詳解mysql的鎖機制

詳解mysql的鎖機制

青灯夜游
青灯夜游原創
2019-11-25 18:29:133338瀏覽

這段時間一直在學習mysql資料庫。專案組一直用的是oracle,所以對mysql的了解也不深。本文主要是對mysql鎖定的總結。

詳解mysql的鎖機制

Mysql的鎖定主要分為3大類:

表格層級鎖定:儲存引擎為Myisam#。鎖住整個表,特點是開銷小,加鎖快,鎖定力度大,發生鎖衝突的機率最高,並發度最低。

頁級鎖定:儲存引擎為BDB#。鎖住某一頁的資料(16kb#左右),特徵:開銷和枷鎖時間介於表級和行級之間;會出現死鎖,鎖定力度介於表鎖和行鎖之間,並發度一般。

行級鎖定:儲存引擎為innodb。鎖住某一行的數據,特點:鎖的實現更加複雜,開銷大,加鎖速度慢。

根據上述特點,僅從鎖的角度來說:表級鎖定更適合以查詢為主,只有少量以索引條件更新資料的應用,如Web 應用;而行級鎖定則更適合於有大量按索引條件並發更新少量不同數據,同時又有並發查詢的應用,如一些在線事務處理(OLTP)系統。

接下來進行行級鎖定的詳解,行級鎖定主要分為以下7類別:共用/ #排他鎖、意向鎖、記錄鎖、間隙鎖、臨車鎖、插入意向鎖、自增鎖。

共享/排他鎖:

#共享鎖定:又稱為讀鎖,可以允許讀取,但不能寫。共享鎖可以與共享鎖一起使用。 語句:

select ... lock in share mode

排他鎖:又稱寫鎖,不能允許讀,也不能允許寫,排他鎖不能與其他所一起使用。 語句:

select ... for update

mysql中,updatedeleteinsertalter這些寫的操作預設都會加上排他鎖定。 Select預設不會加任何鎖定類型。一旦寫資料的任務沒有完成,資料是不能被其他任務讀取的,這對並發操作有較大的影響。

意圖鎖定:innoDB為了支援多粒度的鎖定,即允許行級鎖定和表格層級鎖定共存,而引入意向鎖定。意向鎖是指未來的某個時刻,事務可能要加共享/排他鎖,先事先宣告一個意向。這樣如果有人嘗試對全表進行修改,就不需要判斷表中的資料是否被加鎖了,只需要透過等待意向互斥鎖被釋放就行了。

   意圖共享鎖定(IS):交易想要在取得表格中某些記錄的共享鎖定,需要在表格上先加意向共享鎖。

   意圖互斥鎖定(IX):交易想要在取得表中某些記錄的互斥鎖,需要在表上先加意向互斥鎖。

意向锁其实不会阻塞全表扫描之外的任何请求,它们的主要目的是为了表示是否有人请求锁定表中的某一行数据。

  记录锁(RS):单个行记录上的锁。记录锁总是会锁住索引记录,如果innoDB存储引擎表

在建立的时候没有设置任何一个索引,那么innoDB存储引擎会使用隐式的主键来进行锁定。

间隙锁(GR):间隙锁锁住记录中的间隔,即范围查询的记录。

 Select * From user where id between 1 and 10 for update

这个脚本会锁住110 的数据,以防止其他事务修改该区间的记录;

间隙锁的主要目的,就是为了防止其他事务在间隔中插入数据,以导致“不可重复读”。如果把事务的隔离级别降级为读提交(Read Committed, RC),间隙锁则会自动失效

临建锁(next-key Locks):临建锁是记录锁和间隙锁的组合,锁的范围既包含记录又包含索引区间。默认情况下,innoDB使用临建锁来锁定记录。但当查询的索引含有唯一属性的时候,临建锁会进行优化,将其降级为记录锁,即仅锁住索引本身,不是范围。

临键锁的主要目的,也是为了避免幻读(Phantom Read)。如果把事务的隔离级别降级为RC,临键锁则也会失效。

插入意向锁(insert intention locks):对已有数据行的修改和删除,必须加互斥锁,对于数据的插入,加插入意向锁。是专门针对于insert操作的。

自增锁(auto-inc locks):是一种特殊的表级别的锁,专门针对事务插入auto-increment类型的列。最简单的情况,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。

---------------------------------------------------------分界线--------------------------------------------------------------

接下看讲一下其他的锁:

死锁:产生是因为线程锁之间交替等待产生的。值两个或两个以上的事务在执行过程中,因争夺资源而造成的一种相互等待的现象。

Mysql处理死锁的方法:根据数据写的数据量的大小来回滚小事务。

乐观/悲观锁:

乐观锁:乐观的假定大概率不会发生并发更新冲突,访问,处理数据的过程中不加锁,只在更新数据时根据版本号或时间戳判断是否有冲突,有则处理,无责提交事务。

如果系统并发量非常大,悲观锁会带来非常大的性能问题,选择使用乐观锁,现在大部分应用属于乐观锁

悲观锁:悲观的假定大概率会发生并发更新冲突,访问,处理数据前就加排他锁,在整个数据处理过程中锁定数据,事务提交或回滚后才释放锁。

优点:

悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。

缺点:

a)在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;

b) 在只讀型交易處理中由於不會產生衝突,也沒必要使用鎖,這樣做只能增加系統負載;還有會降低了並行性,一個交易如果鎖定了某行數據,其他交易就必須等待該交易處理完才可以處理那行數

#建議:

  1. 控制交易的大小(操作寫的資料量)
  2. 使用鎖定的時候盡量要配合與攜帶索引的欄位使用,避免升級為表格鎖定
  3. 範圍查詢,盡量減少基於範圍查詢的交易的大小
  4. 如果業務必須要使用鎖,鎖的衝突特別高的話,改為表鎖
  5. 可以根據專案本身的情況調節交易的innodb_flush_log_at_trx_commit

#推薦學習:MySQL教學

#

以上是詳解mysql的鎖機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn