MySQL 頁分裂中的鎖3
資料在插入的過程中先進行樂觀插入,失敗使用悲觀插入。在導致分頁的記錄插入使用了悲觀插入。
悲觀插入中是持有tree的x-latch,分裂的時候,下一層的指標式node_ptr,dict_index_build_node_ptr 這個函式建立,node_ptr也是一個邏輯記錄,根據下一層的第一個記錄中的主鍵進行建立,建立後,當作記錄插入到頁中。
root節點的分裂過程
分配一個新頁,複製root 記錄到新頁,清空root,放入node_ptr ,分裂新頁。需要將root中supremum上的鎖複製到新頁。
分裂新頁的時候,先去嘗試插入到右邊的兄弟節點,不行在確認分裂點
btr_page_get_split_rec_to_right 是否向右分裂,具體是根據PAGE_LAST_INSERT去判斷
lock_update_split_right進行了鎖的更新
將左頁的supremum鎖複製到右頁上
右頁上的第一個記錄的鎖給左頁的 supremum上,如果這個是因為update導致的分裂,那麼這個操作導致鎖範圍加大了。
如果對頁的第一個記錄加鎖,由於掃描方式的問題,導致左面頁的 supremum會加鎖,這個也是鎖放大的一個行為。
下面針對這2個進行下測試。
第一個場景
Create Table: CREATE TABLE `t` ( `a` int(11) NOT NULL, `b` blob, PRIMARY KEY (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 session 1 mysql> insert into t values(1,repeat('a',7000)); Query OK, 1 row affected (0.03 sec) mysql> insert into t values(5,repeat('b',7000)); Query OK, 1 row affected (0.05 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update t set b=repeat('d',7000) where a=5; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0
session 2 mysql> insert into t values(10,repeat('c',7000)); Query OK, 1 row affected (0.03 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into t values(2,repeat('t',7000)); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
可以看到session2的操作是被阻塞了。
第二個場景測試
session 1 begin; select * from t where a=5 lock in share mode;
session 2 ysql> insert into t values(3,repeat('t',7000)); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
這兩個場景都是跟掃描方式有關,但是這種鎖放大有必要嗎,已經可以找到具體記錄了,這種鎖應該可以具體到行了,沒必要加範圍了。
上面的堆疊如下
mysqld!lock_update_split_right(buf_block_t const*, buf_block_t const*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/lock/lock0lock.cc:3266) mysqld!btr_page_split_and_insert(unsigned long, btr_cur_t*, unsigned long**, mem_block_info_t**, dtuple_t const*, unsigned long, mtr_t*) (Unknown Source:0) mysqld!btr_root_raise_and_insert(unsigned long, btr_cur_t*, unsigned long**, mem_block_info_t**, dtuple_t const*, unsigned long, mtr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/btr/btr0btr.cc:1779) mysqld!btr_cur_pessimistic_insert(unsigned long, btr_cur_t*, unsigned long**, mem_block_info_t**, dtuple_t*, unsigned char**, big_rec_t**, unsigned long, que_thr_t*, mtr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/btr/btr0cur.cc:3454) mysqld!row_ins_clust_index_entry_low(unsigned long, unsigned long, dict_index_t*, unsigned long, dtuple_t*, unsigned long, que_thr_t*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0ins.cc:2632) mysqld!row_ins_clust_index_entry(dict_index_t*, dtuple_t*, que_thr_t*, unsigned long, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0ins.cc:3328) mysqld!row_ins_index_entry(dict_index_t*, dtuple_t*, que_thr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0ins.cc:3437) mysqld!row_ins_index_entry_step(ins_node_t*, que_thr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0ins.cc:3587) mysqld!row_ins(ins_node_t*, que_thr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0ins.cc:3725) mysqld!row_ins_step(que_thr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0ins.cc:3861) mysqld!row_insert_for_mysql_using_ins_graph(unsigned char const*, row_prebuilt_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0mysql.cc:1746) mysqld!row_insert_for_mysql(unsigned char const*, row_prebuilt_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0mysql.cc:1866) mysqld!ha_innobase::write_row(unsigned char*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/handler/ha_innodb.cc:7612) mysqld!handler::ha_write_row(unsigned char*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/handler.cc:8093) mysqld!write_record(THD*, TABLE*, COPY_INFO*, COPY_INFO*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_insert.cc:1895) mysqld!Sql_cmd_insert::mysql_insert(THD*, TABLE_LIST*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_insert.cc:776) mysqld!Sql_cmd_insert::execute(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_insert.cc:3140) mysqld!mysql_execute_command(THD*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:3606) mysqld!mysql_parse(THD*, Parser_state*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:5584) mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1491)
有興趣學習原始碼的加群一起學習啊 QQ: 700072075
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25719946/viewspace-2916097/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一看就懂的:MySQL資料頁以及頁分裂機制MySql
- 【MySQL】MySQL中的鎖MySql
- mysql innodb的行鎖(3)MySql
- MYSQL中的那些鎖MySql
- 【MySQL】MySQL中的鎖機制MySql
- MySql(三) MySql中的鎖機制MySql
- Mysql中的鎖機制——MyISAM表鎖MySql
- MySQL中鎖的分類MySql
- MySQL 中的鎖有哪些型別,MySQL 中加鎖的原則MySql型別
- Mysql中S 鎖和 X 鎖的區別MySql
- MySQL InnoDB 中的鎖機制MySql
- MYSQL中的鎖必知必會MySql
- MySQL 當中的各種鎖(中級篇)MySql
- 優化MySQL中的分頁優化MySql
- 優化 MySQL 中的分頁優化MySql
- MySQL/InnoDB中,樂觀鎖、悲觀鎖、共享鎖、排它鎖、行鎖、表鎖、死鎖概念的理解MySql
- 利用MySQL中的樂觀鎖和悲觀鎖實現分散式鎖MySql分散式
- MySQL中鎖的相關問題DTQUMySql
- MySQL的鎖MySql
- (3)mysql 中的運算子MySql
- SQLServer的死鎖分析(1):頁鎖SQLServer
- 【Mysql】InnoDB 引擎中的頁目錄MySql
- 索引分裂的enq索引ENQ
- 詳解 MySql InnoDB 中的三種行鎖(記錄鎖、間隙鎖與臨鍵鎖)MySql
- MySQL實戰 | 06/07 簡單說說MySQL中的鎖MySql
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- 簡單瞭解 MySQL 中相關的鎖MySql
- MySQL中的事務原理和鎖機制MySql
- [Java併發系列] 3.Java中的鎖Java
- mysql鎖之死鎖MySql
- MySQL鎖之三:MySQL的共享鎖與排它鎖編碼演示MySql
- MySQL中的事務和鎖簡單測試MySql
- (16)mysql 中的表鎖定及事務控制MySql
- MySQL的共享鎖和獨佔鎖MySql
- MySQL鎖MySql
- mysql 鎖MySql
- [Mysql]鎖MySql
- 【問答分享第一彈】MySQL鎖總結:MySQL行鎖、表鎖、排他鎖、共享鎖的特點MySql