innodb 引擎 行锁与表锁
 行锁与表锁是基于索引来说的(且索引要生效)

不带索引 (表锁)要全表扫描
  1. 执行select @@autocommit; 查看结果 0是不自动提交事务,1是自动提交事务, mysql默认是自动提交
  2. set autocommit = 0;设置为不开启自动提交
  3. 通过开多个tab窗口模拟不通的session 执行数据库
   新建一张person表

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

       mysql的innodb 引擎 表锁与行锁 随笔 第1张

  窗口1 模拟第一个session

    mysql的innodb 引擎 表锁与行锁 随笔 第2张

在此窗口先执行设置0,在单独执行update语句

   窗口2 模拟第二个session

  mysql的innodb 引擎 表锁与行锁 随笔 第3张

  执行该条语句可以看到 sql一直执行 卡住了,因为它是在等待上一个事务执行完释放表锁

  经过一段时间后看到如下结果

  mysql的innodb 引擎 表锁与行锁 随笔 第4张

   这个错跟我们生产上报的错一样,用pinpoint监控的

  ------------------------------------------------------

  mysql的innodb 引擎 表锁与行锁 随笔 第5张

  执行update 和insert 都是一样的结果 在等待表锁,虽然我操作的不是同一行数据。

  如果我把窗口1的事务提交则窗口2会从卡的状态成功执行结束

       mysql的innodb 引擎 表锁与行锁 随笔 第6张

       窗口1的commit;

    mysql的innodb 引擎 表锁与行锁 随笔 第7张

   窗口2的session的则立马执行完毕, 

   这个场景模拟的是表锁,当session1 拿到表锁后,别的事务的session执行(insert,update,delete) 是拿不到锁的会进行锁等待。

  mysql的innodb 引擎 表锁与行锁 随笔 第8张

  通过命令 看到了当前处于等待的语句

 

  把name字段添加索引(行锁)不用全表扫描直接定位到行 ,使用主键也是用的行锁

      mysql的innodb 引擎 表锁与行锁 随笔 第9张

      添加索引,然后通过执行计划查看索引是生效的

      在回到之前的问题,窗口1 再次执行相同的sql 不提交事务,此时执行窗口2

   mysql的innodb 引擎 表锁与行锁 随笔 第10张

mysql的innodb 引擎 表锁与行锁 随笔 第11张

    窗口2 直接执行完毕,此时行锁生效,我操作的不是同一行,结果生效了

 

 以上是innodb引擎的表锁 和行锁 ,顺便验证一下默认的事务隔离级别(读已提交的)

   开一个窗口3 代表session3

  事务执行前

  mysql的innodb 引擎 表锁与行锁 随笔 第12张

   删掉刚才的索引  drop  index namex_name on person;

   窗口1 执行,当前事务下的结果改变了

   mysql的innodb 引擎 表锁与行锁 随笔 第13张

 

   窗口3验证   窗口1的事务没提交前 别的事务是读不到这个事务的,如果把窗口1的事务提交  怎窗口3能顺利读取, 这同时说明了2个隔离级别  -----------读已提交的 和不可重读

   事务的可串行化可参考:https://blog.csdn.net/nangeali/article/details/75578787  事务内的查询都是带锁的(表锁)

  mysql的innodb 引擎 表锁与行锁 随笔 第14张

  表锁与行锁  以上自己通过数据库执行 直观的验证了一遍,可以看如下这边文章的文字描述来抽象这个验证

    参考:https://blog.csdn.net/lz710117239/article/details/71762617

    https://blog.csdn.net/u014635472/article/details/79712931 或者 https://www.cnblogs.com/wodebudong/articles/7976474.html

  

   总结:   普通的 曾删改  是表锁,加入索引的曾删改 是行锁,执行 查询是不加任何锁的, 不是有些博客所说的 表锁升级为行锁 。

   

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄