# monitor **Repository Path**: bst_cn/monitor ## Basic Information - **Project Name**: monitor - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-04-10 - **Last Updated**: 2022-12-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 关系型DB ### 1.行锁 (索引记录锁) ![](./doc/当前读.png) 注意:根据上图的交互,针对一条当前读的SQL语句,InnoDB 与 MySQL Server 的交互,是一条一条进行的,因此,加锁也是一条一条进行的。先对一条满足条件的记录加锁,返回给 MySQL Server,做一些 DML 操作;然后在读取下一条加锁,直至读取完毕 其实 mysql server 层和存储引擎层的交互是以记录为单位的   拿下面这个 sql 举例子: delete * from lock_test where v1 >= 6 1   首先,mysql server 请求 Innodb 层 v1 建立的二级索引,把 v1 >= 6 作为检索条件交给存储引擎,获取到 v1 >= 6 的第一条记录(假设第一条记录 v1 = 6, 在 InnoDB 层 return v1 = 6 的记录时候,对它加了 X 锁),然后 mysql service 进行回表操作,拿着 v1 = 6 记录中的主键 ID(假设ID=6) 请求 InnoDB 层主键索引,获取到 id = 6 的记录(在 InnoDB 层 return id = 6 的记录时候,对它加了 X 锁),至此一条记录加锁完成;mysql server 还将继续请求 InnoDB 获取 v1 = 6 记录的下一条记录,直至读取完毕;读取完毕后,如果还有 where 条件,则进行 where 条件过滤; 获取行锁成功,事务id:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=294921tableName=t_bst}key=6003} 获取行锁成功,事务id:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=294921tableName=t_bst}key=6004} 获取行锁成功,事务id:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=294921tableName=t_bst}key=6005} 获取行锁成功,事务id:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=294921tableName=t_bst}key=6006} 获取行锁成功,事务id:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=294921tableName=t_bst}key=6007} 获取行锁成功,事务id:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=294921tableName=t_bst}key=6008} 获取行锁成功,事务id:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=294921tableName=t_bst}key=6009} 获取行锁成功,事务id:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=294921tableName=t_bst}key=6010} ![](./doc/锁等待.png) =====================================锁重入、锁升级=================================================================== 获取行锁成功 事务ID:1,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=9tableName=t_bst}key=1} 等待获取锁 等待获取锁 释放行锁成功 事务ID:1 锁类型:XLock rowID:RowId{pageID=BPTreePageID{offset=9tableName=t_bst}key=1} 获取行锁成功 事务ID:2,锁类型:SLock, rowID:RowId{pageID=BPTreePageID{offset=9tableName=t_bst}key=1} 1 等待获取锁 获取SLock成功 锁重入 1 释放行锁成功 事务ID:2 锁类型:SLock rowID:RowId{pageID=BPTreePageID{offset=9tableName=t_bst}key=1} 获取行锁成功 事务ID:3,锁类型:XLock, rowID:RowId{pageID=BPTreePageID{offset=9tableName=t_bst}key=1} primary key already exists 释放行锁成功 事务ID:3 锁类型:XLock rowID:RowId{pageID=BPTreePageID{offset=9tableName=t_bst}key=1} ### 2.全表扫描 ![](./doc/全表扫描.png) 触发当前读,v2 没有索引,where v2 = 6 这个条件也就没法通过二级索引来过滤,那么只能通过主键索引走全表扫描。对于这个sql会加什么锁?主键索引上所有的记录都会被加上 X锁,但是经过 mysqlServer 的条件过滤后,不符合条件的记录会被放锁 ### 3.不存在的记录 delete from lock_test where id = 8; or delete from lock_test where v1 = 8; 触发当前读,但是 id = 8 和 v1 = 8的记录是不存在的,所以也没办法对记录上X锁。 ### 4.加锁解锁时机 1.快照读不需要加锁 (未实现) 2.当前读获取页锁 在获取page的时候加锁 (已实现) 3.当前读获取行锁 在获取row的时候加锁 (已实现) 4.释放 行锁 页锁 在事务提交或者回滚的时候释放 (已实现)