前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文看懂Mysql锁

一文看懂Mysql锁

作者头像
六月的雨在Tencent
发布2024-03-29 08:59:59
1870
发布2024-03-29 08:59:59
举报
文章被收录于专栏:CSDNCSDN
一文看懂Mysql锁

Mysql锁

既然说到了Mysql锁,那么什么是Mysql锁呢?本质上来说,锁是一种协调多个进程或者多个线程对某一资源的访问的机制,Mysql通过锁实现了事务的隔离级别;通俗来说就是当应用访问某一资源时,会对当前资源加锁,防止其他请求来访问该资源,导致产生问题,待当前应用对这一资源访问结束后再释放锁供其他请求获取该资源。

Mysql锁的分类

Mysql锁主要从以下几个方面来分类

从性能上

Mysql锁可以分为悲观锁和乐观锁: 悲观锁:就是说不相信在整个数据处理过程中其他应用不会修改数据库中的数据,一旦获取资源就立刻加锁,在整个数据处理过程中都将相应数据锁定,其他应用无法修改数据。读数据需要加锁,此时不能对这些数据进行修改操作;修改数据也需要加锁,此时不能对这些数据进行读取操作。 乐观锁:就是说为数据增加一个版本标识,查询数据时会将版本号标识一起读出来,在更新数据时,令版本号加1,提交数据时与数据库记录版本对比,如果提交版本号大于数据库中版本号则修改,否则不能修改。

从操作类型上

Mysql锁分为读锁和写锁: 读锁:也叫做共享锁,同一份数据可以加多个读锁。 写锁:也叫做排他锁,如果当前数据的写锁未释放,则不能再加写锁或读锁。

从锁的粒度上

Mysql锁分为表锁、行锁和页面锁: 表锁:就是整个表加锁,开销小,加锁快,一般不会死锁,锁粒度比较大,发生冲突概率性高。 行锁:就是在数据行上加锁,开销比较大,加锁慢,可能会死锁,锁粒度最小,发生冲突概率小,并发高。 页面锁:就是页面级别加锁,开销介于表锁和行锁之间,可能会死锁,锁粒度介于表锁和行锁之间。 从锁的粒度上还有两种锁:间隙锁和临键锁,这两种锁遇到的不到,这里就不再详细阐述了,有兴趣的小伙伴可以自行搜索相关文章介绍。

死锁

既然上面说到了可能会死锁,那么死锁是怎么产生的呢?什么情况下会出现死锁?如何避免死锁呢?

死锁的四个条件

产生死锁需要四个必要条件:互斥条件、不可剥夺条件、请求保持条件、循环等待条件。 互斥条件:就是说某个资源只能被以及各进程或者线程占用,其他进程或线程请求该资源必须等待。 不可剥夺条件:就是说某个资源在该进程或线程使用完之前,不能强行被剥夺,只能由其自行释放。 请求保持条件:有一个进程或者线程已经获得了一个资源,现在要请求其他资源,但请求的其他资源被其他进程占用,此时请求被阻塞,并且不会释放自己的资源。 循环等待条件:有A、B、C三个进程或者线程同时占用自己的资源同时又想获取别的资源

图中A占用自己资源同时请求B的资源,B占用自己资源同时请求C资源,C占用自己资源同时请求A资源,这样就行程了循环等待。

死锁的验证

开启客户端A、B连接Mysql数据库,只需要通过其中一个客户端A创建数据库,数据表即可

代码语言:javascript
复制
create database mytest;

查看数据库创建成功与否

代码语言:javascript
复制
show databases;

选中当前数据库,创建数据表sys_user并插入数据

代码语言:javascript
复制
use mytest;
CREATE TABLE `sys_user` (
  `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID',
  `login_name` varchar(30) NOT NULL COMMENT '登录账号',
  `user_name` varchar(30) DEFAULT '' COMMENT '用户昵称',
  `user_type` varchar(2) DEFAULT '00' COMMENT '用户类型(00系统用户 01注册用户)',
  `email` varchar(50) DEFAULT '' COMMENT '用户邮箱',
  `phonenumber` varchar(11) DEFAULT '' COMMENT '手机号码',
  `sex` char(1) DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
  `avatar` varchar(100) DEFAULT '' COMMENT '头像路径',
  `password` varchar(50) DEFAULT '' COMMENT '密码',
  `salt` varchar(20) DEFAULT '' COMMENT '盐加密',
  `status` char(1) DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',
  `del_flag` char(1) DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
  `login_ip` varchar(50) DEFAULT '' COMMENT '最后登陆IP',
  `login_date` datetime DEFAULT NULL COMMENT '最后登陆时间',
  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户信息表';

INSERT INTO `sys_user` VALUES ('1', '103', 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '29c67a30398638269fe600f73a054934', '111111', '0', '0', '127.0.0.1', '2020-11-24 13:32:43', 'admin', '2018-03-16 11:33:00', 'ry', '2020-11-24 13:32:15', '管理员');
INSERT INTO `sys_user` VALUES ('2', '105', 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '8e6d98b90472783cc73c17047ddccf36', '222222', '0', '0', '127.0.0.1', '2018-03-16 11:33:00', 'admin', '2018-03-16 11:33:00', 'ry', '2018-03-16 11:33:00', '测试员');

在当前客户端A设置事务隔离级别可重复读,开启事务,为user_id=1数据添加排他锁

代码语言:javascript
复制
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM sys_user WHERE user_id=1 FOR UPDATE;

命令行执行结果

同样在客户端B对user_id=2进行相同操作,执行结果如图

之后在终端A为user_id=2添加排他锁,线程卡住,返回错误信息

错误信息

代码语言:javascript
复制
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

此时在终端B为user_id=1添加排他锁,返回错误信息

错误信息内容

代码语言:javascript
复制
1213 - Deadlock found when trying to get lock; try restarting transaction

通过命令查看Mysql死锁信息

代码语言:javascript
复制
SHOW ENGINE INNODB STATUS;

结果如图

或者可以通过命令查看锁信息

代码语言:javascript
复制
select * from information_schema.innodb_trx;

查询结果如图

死锁的避免

1.尽量让数据检索都通过索引完成,避免无效索引导致行锁升级成了表锁; 2.合理设计索引,尽量缩小锁的范围; 3.尽量控制事务大小,减少一次事务锁定的资源数量,缩短资源锁定时间; 4.尽量减少查询条件范围; 5.尽可能使用低级别的事务隔离机制。

总结

以上就是Mysql锁相关内容,希望对大家有所帮助。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一文看懂Mysql锁
  • Mysql锁
    • Mysql锁的分类
      • 从性能上
      • 从操作类型上
      • 从锁的粒度上
    • 死锁
      • 死锁的四个条件
      • 死锁的验证
      • 死锁的避免
    • 总结
    相关产品与服务
    云数据库 MySQL
    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档