本文以为例,为大家分析Mysql中键锁的使用方法,阅读完整文相信大家对有了一定的认识。
连接与线程
查看连接信息<代码>显示processlist 代码>
<代码> +——+ + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | | |用户Id主机,,,,,,| db,| | |命令时间状态,|信息大敌;,,,,,| + - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 3,| | |根172.17.0.1:60542 | |查询测试,| 0,开始,| |显示processlist | 5,| | |根172.17.0.1:60546 | |测试睡眠,| 4168 |,,,,,| & lt; null>,,,,,| 8,| | |根172.17.0.1:60552 | |测试睡眠,| 4170 |,,,,,| & lt; null>,,,,,| + - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 代码>
mysql非企业版本只支持一个线程一个链接
查看线程模型<代码>显示变量如& # 39;thread_handling& # 39; 代码>
<代码> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Variable_name,,,,,,,,,,,,,|值,,,,,,,,,,| + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | thread_handling,,,,,,,,,,,,|每个连接一个线程的| + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 代码>
【事务提交策略】
有两个隐藏事务提交时间点需要注意,第一个是<代码> autocommit=1 代码> Mysql会话级别的自动提交变量,所有, ORM 框架中的事务提交控制都会受到这个字段影响,默认情况下当前语句会自动提交,但是如果是显示 开始事务开启事务需要自行手动提交。有些时候ORM框架会根据一些设置或者策略,将自动提交 设置为0。
第二个就是,DDL操作前都会隐式提交当前事务,有些脚本将DML和DDL混合在一起使用,这样会有一致性问题.DDL会自动提交当前事务。因为DDL在5.7之前都是不支持事务原则操作的。(Mysql8.0已经支持DDL事务性)
键锁排查
键锁只发生在 RR(可重复读)隔离级别下。
Mysql有很多类型对种锁,<代码>表锁代码>,<代码>记录锁代码>,<代码>差距锁代码>,<代码>意向共享/排他锁代码>,<代码>插入意向锁代码>,<代码>元数据锁代码>,<代码> Auto_Incr自增锁> 代码,排除掉元数据锁, Auto_Incr自增锁之后,剩下的锁组合使用最多的就是在RR隔离级别下。
RR隔离级别是默认事务隔离级别,也是Mysql的强项之一,在RR隔离级别下事务有最大的吞吐量,而且不会出现幻读问题.Next-Key锁就是为了解决这个问题,简单讲记录锁锁 +差距就是 键锁。
_幻读_的根本问题就是出现在记录的边界值上,比如我们统计年龄大于30岁的人数:<代码> select count(1)人民age& gt; 代码>这30个语句有可能每次查询得到的结果集都是不一样的,因为只要符合 age> 30 的记录进到我们的 人民表中就会被查询条件命中。
所以要想解决幻读不仅不允许记录的空隙被插入记录外,还要防止两遍记录被修改,因为如果前后两条记录被修改了那区间就会变大,就会有幻读出现。
我们看个例子。
<代码>创建表的人的( ,“id”int(11)无符号不是零AUTO_INCREMENT, ,“年龄”int(11)默认为空, ,主键(“id”), ,关键“idx_peoples_age”(“年龄”) )引擎=InnoDB AUTO_INCREMENT=1的默认字符集=utf8mb4 代码>
<代码> +——+——+ 年龄| | | id + - - - + - - - + | 1,20 | | 30 2,| | | 35 3,| | | 40 | 4,| | + - - - +——+ 代码>
为了方便调试,将innodb获取锁的超时时间调大点
<代码>显示变量如& # 39;% innodb_lock_wait % & # 39; 设置innodb_lock_wait_timeout=600 代码>
开启两个会话。
<代码>会话id=8: 开始 选择计数(1)从人民那里age> 30更新;代码>
<代码> B会话id=5: 开始 插入人民(年龄)值(31)代码>
<代码>显示processlist 代码>找到连接的id。
<代码> * * * * * * * * * * * * * * * * * * * * * * * * * * * (1。行)* * * * * * * * * * * * * * * * * * * * * * * * * * * 身份证,,3,| 用户,,|根 主机,,| 172.17.0.1:60542 db,,,|测试 命令|查询 时间,,| 0 状态,|开始 信息,| processlist展示 * * * * * * * * * * * * * * * * * * * * * * * * * * * (2。行)* * * * * * * * * * * * * * * * * * * * * * * * * * * 身份证,,5,| 用户,,|根 主机,,| 172.17.0.1:60546 db,,,|测试 命令|查询 时间,394年,| 状态,|更新 信息,,|插入人民(年龄)值(31) * * * * * * * * * * * * * * * * * * * * * * * * * * * (3。行)* * * * * * * * * * * * * * * * * * * * * * * * * * * 身份证,,8,| 用户,,|根 主机,,| 172.17.0.1:60552 db,,,|测试 睡眠命令| 时间,396年,| 状态,| 信息,代码,| & lt; null>Mysql中键锁的使用方法