MySQL 页分裂中的锁3

来源:这里教程网 时间:2026-03-01 16:50:03 作者:

数据在插入的过程中先进行乐观插入,失败使用悲观插入。在导致分页的记录插入使用了悲观插入。悲观插入中是持有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

相关推荐