MySQL InnoDB存储引擎select和update查询阻塞insert语句,形成表级锁
大约在两个月前,有同事在使用 Select 查询语句的时候,发现整张表被锁了,导致日志中经常出现 time out 异常。当时我判断是 select 不可能锁表的,而且更不可能锁整张表。直到今天我抽出时间查询资料,才发现不仅 Select 会锁整张表,Update 和 delete 都会锁整张表,这里面的原因且听本文分解!
InnoDB 的细粒度行锁以及事务支持一度是 MySQL 最吸引人的特性之二。但是在多种情况下,InnoDB 的行级锁会变成表级锁。使用不当,给我们带来的危害极大!
如果 InnoDB 的查询没有命中索引,也将退化为表锁。InnoDB 的细粒度锁,是实现在索引记录上的。
InnoDB 的索引有两类。聚集索引(Clustered Index)与普通索引(Secondary Index)。
InnoDB 的每一个表都会有聚集索引。如果你没手动创建,InnoDB 也会默认的帮你创建聚集索引。
聚集索引以下面三种形式存在:
-
如果表定义了 PK,则 PK 就是聚集索引;
-
如果表没有定义 PK,则第一个非空 unique 列是聚集索引;
- 否则,InnoDB 会创建一个隐藏的 row-id 作为聚集索引。
我们知道索引的结构是 B+ 树,这里不展开 B+ 树的细节,先说几个结论:
-
在索引结构中,非叶子节点存储 key,叶子节点存储 value;
-
聚集索引,叶子节点存储行记录(row);
- 普通索引,叶子节点存储了 PK 的值。
由于上面我们说过的 InnoDB 的每一个表都会有聚集索引,索引结构中叶子节点存储 value,而聚集索引的叶子节点还会存储行记录(row)。所以,InnoDB 索引和记录是存储在一起的,而 MyISAM 的索引和记录是分开存储的。
所以,InnoDB 的普通索引,实际上会扫描两遍:第一遍,由普通索引找到 PK;第二遍,由PK找到行记录;
关于索引结构,我这里不展开去讲,后面我查询更多资料后,将给大家详细的讲讲 InnoDB/MyISAM 的索引结构,如果大家感兴趣的话。
下面我们通过一个例子来说明。假设存在一个下面结构的 InnoDB 表:
1 xttblog(id PK, name KEY, sex, flag);
表中有四条记录:
1, shenjian, m, A 3, zhangsan, m, A 5, lisi, m, A 9, wangwu, f, B
从上图中可以看到:
-
第一幅图,id PK的聚集索引,叶子存储了所有的行记录;
- 第二幅图,name上的普通索引,叶子存储了PK的值;
当执行查询 select * from t where name=’shenjian’; 语句时,会发生下面的过程:
-
会先在 name 普通索引上查询到PK=1;
- 再在聚集索引衫查询到(1,shenjian, m, A)的行记录;
再回到文章开头部分,我们说过“InnoDB 的查询没有命中索引,也将退化为表锁。InnoDB 的细粒度锁,是实现在索引记录上的。”由于这里的 name 并没有创建索引,所以它会变成表锁。至于时读锁和写锁,它们都是锁。InnoDB 的锁,与索引类型,事务的隔离级别相关。InnoDB 一共有 7 种锁,后面有时间了等我查资料,我们再一起来学习!
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763,QQ2群:454796847,QQ3群:187424846。QQ群进群密码:xttblog,想加微信群的朋友,可以微信搜索:xmtxtt,备注:“xttblog”,添加助理微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!
- Mysql查询语句使用select.. for update导致的数据库死锁分析
- jdbc----mysql的select、insert、update、delete 基本语句
- Mysql update语句赋值嵌套select,更新和查询同一张表,必须取别名;用例:更新指定游戏服务器最后启动记录的结束时间
- SQL基础查询语句1:select,insert,delete,drop,update,where,order,or,limit关键词
- Mysql查询语句使用select.. for update导致的数据库死锁分析
- mysql 中将select查询的值赋给insert语句
- mysql 事务是专门用来管理insert,update,delete语句的,和select语句一点不相干
- MySql基础语句_insert_delete_update_select_另附零长度字符串' '和null的基本区别
- MySQL select、insert、update批量操作语句代码实例
- mysql 将select查询的值赋给update set语句中
- MySql依据查询结果,生成insert、update语句
- MYSQL数据库(十)- 数据表的插入(insert)、删(delete)、改(update)、查(select)、group by 分组、having语句设置分组条件,order by查询结果排序,
- 1.利用android提高的的insert,query,update,deleteAPI与execSql,rawQuery函数执行原生的插入,查询,更新,删除语句操作花费时间的对比结果
- mysql字符集,insert,update,delete,select
- mysql SELECT FOR UPDATE语句使用示例
- MySQL 4.1.0 中文参考手册 --- 6.4 数据操纵:SELECT, INSERT, UPDATE, DELETE
- create 语句和insert 语句和update语句和select语句
- MySQL insert update语句
- Mysql的Select查询语句性能检测工…
- mysql优化SELECT语句和其它查询