日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

9、 InnoDB行锁

發布時間:2025/3/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 9、 InnoDB行锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在 MySQL 中,InnoDB 行鎖通過給索引上的索引項加鎖來實現,如果沒有索引,InnoDB 將通過隱藏的聚簇索引來對記錄加鎖。

InnoDB 支持 3 種行鎖定方式:

  • 行鎖(Record Lock):直接對索引項加鎖。
  • 間隙鎖(Gap Lock):鎖加在索引項之間的間隙,也可以是第一條記錄前的“間隙”或最后一條記錄后的“間隙”。
  • Next-Key Lock:行鎖與間隙鎖組合起來用就叫做 Next-Key Lock。 前兩種的組合,對記錄及其前面的間隙加鎖。

默認情況下,InnoDB 工作在可重復讀(默認隔離級別)下,并且以 Next-Key Lock 的方式對數據行進行加鎖,這樣可以有效防止幻讀的發生。

Next-Key Lock 是行鎖與間隙鎖的組合,這樣,當 InnoDB 掃描索引項的時候,會首先對選中的索引項加上行鎖(Record Lock),再對索引項兩邊的間隙(向左掃描掃到第一個比給定參數小的值, 向右掃描掃到第一個比給定參數大的值, 然后以此為界,構建一個區間)加上間隙鎖(Gap Lock)。如果一個間隙被事務 T1 加了鎖,其它事務不能在這個間隙插入記錄。

要禁止間隙鎖的話,可以把隔離級別降為讀已提交(READ COMMITTED),或者開啟參數 innodb_locks_unsafe_for_binlog。

注意:以上語句描述的情況,與 MySQL 所設置的事務隔離級別有較大的關系。

開啟一個事務時,InnoDB 存儲引擎會在更新的記錄上加行級鎖,此時其它事務不可以更新被鎖定的記錄。下面我們以示例1演示此過程。

例 1
下面的語句需要在兩個命令行窗口中執行。為了方便理解,我們分別稱之為 A 窗口和 B 窗口。

分別在 A 窗口和 B 窗口中查看事務隔離級別,A 窗口和 B 窗口的事務隔離級別需要保持一致。

A 窗口查看隔離級別的 SQL 語句和運行結果如下所示:

mysql> SHOW VARIABLES LIKE 'tx_isolation' \G *************************** 1. row *************************** Variable_name: tx_isolationValue: REPEATABLE-READ 1 row in set, 1 warning (0.03 sec)

B 窗口查看隔離級別 SQL 語句和運行結果如下所示:

mysql> SHOW VARIABLES LIKE 'tx_isolation' \G *************************** 1. row *************************** Variable_name: tx_isolationValue: REPEATABLE-READ 1 row in set, 1 warning (0.03 sec)

結果顯示,A窗口和 B窗口的事務隔離級別都為 REPEATABLE-READ。

在 A窗口中開啟一個事務,并修改 tb_student 表,SQL 語句和運行結果如下:

mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> UPDATE test.tb_student SET age ='30' WHERE id = 1;

在 B窗口中也開啟一個事務,并修改 tb_student 表,SQL 語句和運行結果如下:

mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> UPDATE test.tb_student SET age ='30' WHERE id = 1;

會發現 UPDATE 語句一直在執行。這時我們在 A 窗口中提交事務。

mysql> COMMIT;

這時我們發現 B 窗口中的 UPDATE 語句執行成功。

mysql> UPDATE test.tb_student SET age ='30' WHERE id = 1; Query OK, 0 rows affected (1 min 2.78 sec) Rows matched: 1 Changed: 0 Warnings: 0

查詢 tb_student 表中的數據,SQL 語句和運行結果如下:

mysql> SELECT * FROM test.tb_student; +----+------+------+------+------+ | id | name | age | sex | num | +----+------+------+------+------+ | 1 | 張三 | 30 || 4 | | 2 | 李四 | 12 || 4 | | 3 | 王五 | 13 || 4 | | 4 | 張四 | 13 || 4 | | 5 | 王四 | 15 || 4 | | 6 | 趙六 | 12 || 4 | +----+------+------+------+------+ 6 rows in set (0.00 sec)

如以上實例所示,當有不同的事務同時更新同一條記錄時,另外一個事務需要等待另一個事務把鎖釋放,此時查看 MySQL 中 InnoDB 存儲引擎的狀態如下:

mysql> SHOW ENGINE innodb status \G ...... ------------ TRANSACTIONS ------------ Trx id counter 19556 Purge done for trx's n:o < 19554 undo n:o < 0 state: running but idle History list length 12 LIST OF TRANSACTIONS FOR EACH SESSION: ---TRANSACTION 283572223909376, not started 0 lock struct(s), heap size 1136, 0 row lock(s) ---TRANSACTION 19555, ACTIVE 54 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id 14, OS thread handle 4568, query id 886 localhost ::1 root updating UPDATE test.tb_student SET age ='30' WHERE id = 1 ------- TRX HAS BEEN WAITING 54 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 197 page no 3 n bits 80 index PRIMARY of table `test`.`tb_student` trx id 19555 lock_mode X locks rec but not gap waiting Record lock, heap no 2 PHYSICAL RECORD: n_fields 7; compact format; info bits 0 0: len 4; hex 80000001; asc ;; 1: len 6; hex 000000004c62; asc Lb;;

從上面運行結果可以看出,
SQL 語句 UPDATE test.tb_student SET age ='30' WHERE id = 1 在等待,

RECORD LOCKS space id 197 page no 3 n bits 80 index PRIMARY of tabletest.tb_studenttrx id 19555 lock_mode X locks rec but not gap 表示鎖住的資源,

locks rec but not gap 代表鎖住的是一個索引,不是一個范圍。

“MySQL thread id 14, OS thread handle 4568, query id 886 localhost ::1 root updating”表示第 2 個事務連接的 ID 為 14,當前狀態為正在更新,同時正在更新的記錄需要等待其它事務將鎖釋放。當超過事務等待鎖允許的最大時間,此時會提示“ERROR 1205(HY000):Lock wait timeout exceeded; try restarting transaction" 及當前事務執行失敗,則自動執行回滾操作。

MySQL 數據庫采用 InnoDB 模式,默認參數 innodb_lock_wait_timeout 設置鎖等待的時間是 50s,一旦數據庫鎖超過這個時間就會報錯。

可通過以下命令查看當前數據庫鎖等待的時間。

mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_lock_wait_timeout | 120 | +--------------------------+-------+ 1 row in set, 1 warning (0.02 sec)

下面演示了 InnoDB 間隙鎖的實現機制。

例 2
下面在保證 A 窗口和 B 窗口的前提下,將 tb_student 表中的 id 字段設為外鍵,并開啟一個事務,修改 tb_student 表中 id 為 1 的 age。SQL 語句和運行結果如下:

mysql> ALTER TABLE test.tb_student ADD unique key idx_id(id); mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> UPDATE test.tb_student SET age ='31' WHERE id = 1;

在 B 窗口中開啟一個事務,修改 tb_student 表中 id 為 2 的 age,SQL 語句和運行結果如下:

mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> UPDATE test.tb_student SET age ='28'WHERE id=2;

這時分別提交 A窗口和 B窗口的事務。

mysql> COMMIT; Query OK, 0 rows affected (0.01 sec)

查詢 tb_student 表的數據,SQL 語句和運行結果如下:

mysql> SELECT * FROM test.tb_student; +----+------+------+------+------+ | id | name | age | sex | num | +----+------+------+------+------+ | 1 | 張三 | 31 || 4 | | 2 | 李四 | 28 || 4 | | 3 | 王五 | 13 || 4 | | 4 | 張四 | 13 || 4 | | 5 | 王四 | 15 || 4 | | 6 | 趙六 | 12 || 4 | +----+------+------+------+------+ 6 rows in set (0.00 sec)

在上述示例中,由于 InnoDB 行級鎖為間隙鎖,只鎖定需要的記錄,因此 B窗口中的事務可以更新其它記錄,兩個事務之間互不影響。

總結

以上是生活随笔為你收集整理的9、 InnoDB行锁的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。