外贸网站服务器,手机网站模板 怎样做,免费网站建设公司联系方式,wordpress前端编辑插件首先我们有三张表t1,t2,t3#xff0c;它们都是只有两个字段#xff0c; int类型的id和varchar类型的name#xff1b;区别是t1没有索引#xff0c;t2有主键索引#xff0c;t3有唯一索引。 再强调一次#xff0c;在实验前必须提前关闭自动提交#xff0c;set autocommitof…首先我们有三张表t1,t2,t3它们都是只有两个字段 int类型的id和varchar类型的name区别是t1没有索引t2有主键索引t3有唯一索引。 再强调一次在实验前必须提前关闭自动提交set autocommitoff。然后show variables like autocommit查看自动提交是否是off。 我们先假设InnoDB的锁锁住了是一行数据或者一条记录。
1.假设锁住记录
1.1 实验一没有索引的表(t1)
这个实验操作是操作没有索引的t1t1里面有4条数据1、2、3、4。
现在我们在两个会话里面手工开启两个事务。在第一个事务里面我们通过where id 1 锁住第一行数据。在第二个事务里面我们尝试给id3的这一行数据加锁大家觉得能成功吗
Transaction1Transaction2Begin; SELECT * FROM t1 where id1 FOR UPDATE; Begin; SELECT * FROM t1 where id3 FOR UPDATE; // BLOCKED INSERT INTO t1 (id, name) VALUES (5, ‘5’); // BLOCKED
这就有点奇怪了第一个事务锁住了id1的这行数据为什么我不能操作id3的数据呢我们再来操作一条不存在的数据插入id5。它也被阻塞了。实际上这里整张表都被锁住了。所以我们的第一个猜想被推翻了InnoDB的锁锁住的应该不是Record。
那为什么在没有索引或者没有用到索引的情况下会锁住整张表这个问题我们先留在这里。下面继续看第二个实验。
1.2 实验二有主键索引的表(t2)
我们先看一下t2的表结构。字段是一样的不同的地方是id上创建了一个主键索引。里面的数据是 1、4、7、10。
Transaction1Transaction2Begin; SELECT * FROM t2 where id1 FOR UPDATE; Begin; SELECT * FROM t2 where id1 FOR UPDATE; // BLOCKED SELECT * FROM t2 where id4 FOR UPDATE; // OK
第一种情况使用相同的id值去加锁冲突使用不同的id加锁可以加锁成功。
那么出现问题了从实验一中得到锁定的不是一行数据但是实验二操作不同记录的数据又可以成功那有没有可能是锁住了id的这个字段呢
2.假设锁住字段
我们看一下 t3 的表结构。字段还是一样的 id上创建了一个主键索引name上创建了一个唯一索引。里面的数据是1、4、7、10。
在第一个事务里面我们通过name字段去锁定值是4的这行数据。在第二个事务里面尝试获取一样的排它锁肯定是失败的这个不用怀疑。在这里我们怀疑InnoDB锁住的是字段所以这次我换一个字段用id4去给这行数据加锁大家觉得能成功吗
Transaction1Transaction2Begin; SELECT * FROM t3 where name‘4’ FOR UPDATE; Begin; SELECT * FROM t3 where name‘4’ FOR UPDATE; // BLOCKED SELECT * FROM t3 where id4 FOR UPDATE; // BLOCKED
很遗憾又被阻塞了说明锁住的是字段的这个推测也是错的否则就不会出现第一个事务锁住了name第二个字段锁住id失败的情况。
既然锁住的不是record也不是column InnoDB里面锁住的到底是什么呢
3.其实锁的是索引
在这三个案例里面我们要去分析一下他们的差异在哪里也就是这三张表的结构是什么区别导致了加锁的行为的差异其实答案就是索引。 InnoDB的行锁就是通过锁住索引来实现的。
那索引又是个什么东西为什么它可以被锁住我们在 【MySQL】详谈索引存储结构推演过程 已经分析过了。那么我们还有两个问题没有解决
问题一为什么表里面没有索引的时候实验一锁住一行数据会导致锁表或者说如果锁住的是索引一张表没有索引怎么办所以一张表有没有可能没有索引
如果我们定义了主键(PRIMARYKEY)那么 InnoDB 会选择主键作为聚集索引如果没有显式定义主键则 InnoDB 会选择第一个不包含有 NULL 值的唯一索引作为主键索引如果也没有这样的唯一索引则 InnoDB 会选择内置 6 字节长的 ROWID 作为隐藏的聚集索引它会随着行记录的写入而主键递增
所以实验一为什么锁表是因为查询没有使用索引会进行全表扫描然后把每一个隐藏的聚集索引都锁住了。
问题二实验二为什么通过唯一索引给数据行加锁主键索引也会被锁住
在辅助索引里面 索引存储的是二级索引和主键的值。 比如name4存储的是name的索引和主键id的值4。而主键索引里面除了索引之外还存储了完整的数据。所以我们通过辅助索引锁定一行数据的时候它跟我们检索数据的步骤是一样的会通过主键值找到主键索引然后也锁定。 复杂官网的一句话A record lock is a lock on an index record是不是只有【记录锁】是锁索引其他锁是锁住行或表
回复:行锁、表锁是对于锁粒度而言的是一对最广泛的概念。表锁的实现很好想就是需要一个标志来记录当前有没有事务已经来操做表了。而行锁的实现是锁的索引根据锁索引的范围又可以分为记录锁、间隙锁、临键锁。 比如说我们修改一个数据库已经有的记录那直接锁相应索引就行记录锁再比如我们给一张有两条数据的表id1id10进行范围查询并加锁 where id2 and id 5 for update此时命中了一个不存在数据的区间(2,5)这时该锁哪是锁两个索引之间的整个区间1,10这就是间隙锁。临键锁记录锁间隙锁这里就不说了可以看我的这篇文章 https://blog.csdn.net/weixin_43935927/article/details/109410420