我学习MySQL是半路出家,刚开始接触的时候,只知道数据库的增删改查和事务,直到有一天数据库突然爆出(1205, 'Lock wait timeout exceeded; try restarting transaction'),那时候,我才知道数据库还有锁这么一个玩意。这篇文章简单谈谈我对MySQL锁的理解与总结

一、锁的设计是为了解决什么问题?

我们知道数据库能够支持多用户共同读写,当多用户读写数据的时候,就有可能会出现同一时刻对多个用户对同一条数据的读写,就会出现下面的场景:

大家都只是对这一条数据进行读取

有一部分人想要对这一条数据进行读取,有一部分人想要对这一条数据进行修改

大家都想要对这一条数据进行修改

对于场景1,数据不会变化,大家读到数据都是一样的,

对于场景2,若读数据的人不关心修改后的数据,只关心当前的值,对于读数据的人是没有影响的,对于修改数据的人,问题就出现了,大家都拿去修改了,然后保存了自己修改的值,这样的话,我们要以谁修改的值为准呢,或者后面保存修改值的人会把前面保存的结果给覆盖掉。

对于场景3,写数据会出现和场景2一样的情况。

如何优雅的解决上面的问题呢?数据库引入了锁的概念,数据可以加锁,用来控制对数据的合理访问。对于上面的场景3,当用户1想要修改这一条数据时,必须先获取这一条数据的锁,然后在修改,同时用户2想要修改这一条数据时,也要先获取这一条数据的锁,但锁被用户1获取了,他只能等用户1修改完,释放锁后,才能继续修改这一条数据,这样每个人都能修改数据,就不会乱了。

根据锁的类型可以分为读锁,写锁

根据锁的范围可以分为全局锁,表级锁,行锁

二、读锁,写锁

当我们需要对一个数据进行读取的时候,就需要获取读锁,当我们对一个数据进行修改的时候,就需要获取写锁

读锁之间不互斥,当对一个数据加了读锁后,还可以对它继续加读锁,不能添加写锁

写锁与读锁之间,写锁与写锁之间互斥,当对一个数据加了写锁后,不能继续添加其他锁了,必须要等待写锁释放

三、全局锁

全局锁,会锁住整个数据库,整个数据库不可写入数据,不可修改数据表结构,只能读取数据,这样的话,就保证了整个数据库只读,最典型的应用就是全局备份数据,备份数据期间,我们不希望有数据能写入数据库中,不然后有可能备份后的数据是不完整的数据。

比如有两个表中的数据是关联的,第一张表a,第二张表b,表a增加一条记录时,表b就会记录一条关于表a操作的记录

现在在我们备份的时候,不加全局锁,考虑下面的情况

时刻1. 备份表a

时刻2. 表a插入了一条记录,表b也要记录一条

时刻3. 备份表b

这样的顺序下来,备份后的数据表b中多记录了一次操作

我们可以通过加全局锁,来实现在备份过程中,只能读取数据,无法修改数据,来保证备份后数据的一致性

四、表级锁

表级锁可分为两种,一种是表锁,一种元数据锁(MDL)

MDL锁不需要显示使用,在访问表的时候会自动加上

当要读取一个表时,要获取MDL读锁,当要修改一个表的结构的时候,就要获取MDL写锁。MDL主要是为了防止DDL和DML并发的冲突。

表锁锁一整表,锁的范围还是太大了。

五、行锁

行锁时目前最细粒度的锁了,只有Innodb引擎支持,MYISAM引擎只支持到表级锁

innodb事务开启后,行锁是需要的时候才会加上,但不是不需要了就会立即释放行锁,而是等整个事务提交之后,才会释放行锁。这个就是mysql的两阶段锁协议。

有这么一种场景,一个事务执行中,要执行很多条语句,其中有一条语句会更新同一行数据。当多个事务并发的时候,必定会争夺同一行数据的锁,当一个事务持有锁的时候,其他事务就必须等待。在这种场景下,我们该如何设计语句的执行顺序,让等待的时间最少?

我们已经知道了两阶段锁协议,锁在事务结束的时候才会释放,所以,把更新同一行数据的语句越往后放,等待的时间就会越少。

innodb已经有了行锁,但还是不能够保证并发事务的正确性,为此,innodb引入了新的锁,叫间隙锁,当要更新数据时,在一行行扫描加锁的过程中,不仅会加行锁,还会添加间隙锁,也就数据行之间的锁。

六、总结

MySQL中的锁机制就是为了解决共享资源的问题,为了从不同程度控制资源的读写,相应的引入了全局锁,表级锁,行锁,以及不同锁类型。

mysql中写锁定实例_MySQL中的锁相关推荐

  1. mysql添加新的实例_MySQL中添加新用户权限的实例详解

    有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授权表.比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些. 下面的例子显示出如何使用MySQL客户安装新用户. ...

  2. mysql临时表的使用实例_MySQL中临时表的使用示例

    这两天事情稍微有点多,公众号也停止更新了几天,结果有读者催更了,也是,说明还是有人关注,利己及人,挺好. 今天分享的内容是MySQL中的临时表,对于临时表,之前我其实没有过多的研究,只是知道MySQL ...

  3. mysql里面integer默认宽度_MySQL中关于数据类型指定宽度之后的情况

    概述 MySQL有很多种数据类型,最常用的就是int,char,varchar,这些类型在创建表的时候都可以指定该字段的宽度,方法是在类型后面加一个括号,括号中写宽度就可以了. 但是,在指定宽度之后, ...

  4. mysql中my.cnf文件_MySQL中my.cnf文件选项

    MySQL中my.cnf文件选项 mysqld服务器维护两种变量.全局变量影响服务器的全局操作.会话变量影响具体客户端连接相关操作. 可以在选项文件或命令行中设置全局变量. 用Set命令设置会话变量, ...

  5. mysql按升序创建索引_Mysql中的降序索引底层实现

    什么是降序索引 大家可能对索引比较熟悉,而对降序索引比较陌生,事实上降序索引是索引的子集. 我们通常使用下面的语句来创建一个索引: 上面sql的意思是在t1表中,针对b,c,d三个字段创建一个联合索引 ...

  6. mysql数据库回滚日志_MySQL中是如何实现事务提交和回滚的?

    什么是事务 事务是由数据库中一系列的访问和更新组成的逻辑执行单元 事务的逻辑单元中可以是一条SQL语句,也可以是一段SQL逻辑,这段逻辑要么全部执行成功,要么全部执行失败 举个最常见的例子,你早上出去 ...

  7. mysql得union使用方法_mysql中Union All使用方法

    在mysql数据库使用UNION 时,会把结果集中重复的记录删掉,也正因为做了去重操作,所以效率相对Union All来讲稍微低一点,使用UNION ALL ,MySQL 会把所有的记录返回,效率高于 ...

  8. mysql日期隐式转换_mysql中的隐式转换

    什么隐式类型转换? 在MySQL中: 当操作符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容.则会发生转换隐式 也就是说,MySQL会根据需要自动将数字转换为字符串,将字符串转换数字.看到 ...

  9. mysql去除select换行符_MySQL中去除字段中的回车符和换行符

    问题: 在使用[ load data infile 'D:/node.txt' into table node fields terminated by '\t'; ]语句批量导入如下图所示的aaa. ...

最新文章

  1. 【Linux】 Linux简单操作之网络通信和网络访问
  2. 配置jdk环境 windows
  3. 10个解放双手实用在线工具,有些代码真的不用手写
  4. Swift基础语法 、 元组(Tuple)
  5. OJ4121 and OJ2968-股票买卖 and Maximun sum【各种dp之6 and 9】
  6. python基础——lambda函数
  7. 随想录(libc.so和ld.so调试)
  8. spring整合mybatis的坑
  9. 修改Kubelet的cgroup driver
  10. [转载] python迭代器
  11. 几个关于oracle 11g ASM的问题
  12. 高质量计算机学习网站
  13. 周杰伦要出新专辑了?上 Instagram 看看
  14. Unity 面试题汇总(五)性能优化知识点相关
  15. React Native中的视频编码
  16. wb在计算机知识里是什么意思,计算机二级考试内容是什么?
  17. 如何创建一流技术团队
  18. python文本字符分析
  19. python输入数学表达式并求值_Python 条件表达式求值
  20. Legolas工业自动化平台案例 —— 水源地自动化监控系统

热门文章

  1. Linux的目录结构与磁盘分区
  2. linux 打zip gz tar,linux把文件压缩成.tar.gz的命令 | PT Ubuntu Blog
  3. postgres预写式日志的内核实现详解-wal记录读取
  4. Nginx+FastCGI支持HTTPS部署过程详述
  5. spring-102-spring全注解快速实现事务
  6. wsgiref — WSGI Utilities and Reference Implementation¶
  7. 左神算法进阶班5_3求公司的最大活跃度
  8. 多商铺购物车查询 排除重复商家
  9. mac地址规范及算法
  10. TortoiseGit的安装使用