我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

如果面向多线程高并发的需求的时候,就需要考虑数据完整一致性的问题了。这个时候,一般就会使用“锁”的概念。使用一种手段来保证数据的更新逻辑是独一被执行的。防止脏读、幻读产生的数据不一致等现象。mysqlselect ... for update行级锁就是其中的一种悲观锁的问题解决手段。本文对select ... for update做一下初步的探讨。

苏南大叔:mysql悲观锁,如何理解mysql的select for update行级锁? - mysql行级锁select-for-update
mysql悲观锁,如何理解mysql的select for update行级锁?(图3-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:win10mysql@5.7.26mysql-front@5.3

前文回顾

mysqlselect ... for update不是事务的一部分,但是需要和事务一起搭配使用才能产生效果。这里回顾一下事务的相关文章:

InnoDB

需要特别说明的是:
select ... for update必须配合事务才能发挥效果。所以,也需要innodb存储类型表,不支持MyISAM存储类型。本文的龙套角色数据表如下所示:

DROP TABLE IF EXISTS `innodb`;
CREATE TABLE `innodb` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `innodb` VALUES (1,'苏南大叔'),(2,'sunan大叔');

事务 + for update

因为涉及到多个进程获得同一条数据的操作权限的问题,所以这里模拟了两个进程。一个使用命令行页面下的mysql,另外一个使用mysql-front软件操作界面。

【界面一】命令行进程:

begin;
select * from innodb where id=1 for update;
这里的begin是关键,没有它,for update会完全失效!

苏南大叔:mysql悲观锁,如何理解mysql的select for update行级锁? - 锁定行级别
mysql悲观锁,如何理解mysql的select for update行级锁?(图3-2)

【界面二】此时在软件界面,试图修改数据:

update innodb set name='好市民苏大哥' where id=2;

成功,因为第二条数据没有被锁定。继续操作:

update innodb set name='sunan大叔叔' where id=1;

失败陷入无限等待,因为第一条数据被锁定了。

苏南大叔:mysql悲观锁,如何理解mysql的select for update行级锁? - 等待commit
mysql悲观锁,如何理解mysql的select for update行级锁?(图3-3)

【界面一】回界面一,输入commit命令,结束事务。

commit;

结束事务的同时,界面二更新成功。

注意:这里仅仅验证了行级锁的存在,并没有解决脏数据的问题。因为界面二的输入在解锁后,也成功写入了。它如果没有使用事务的话,这就是一条脏数据。那么,正确的做法是:对这些数据进行操作的时候,都使用事务,都使用for update

一些冷知识

下面是网上教程里面没有写的,仔细看哦。

行级锁

for updatewhere语句很重要,符合where的行将会被锁定。如果不写where的话,或者where的是没有索引的字段的话,锁定的可是一整张表。这会引发大的问题!如果for update查询到的是空数据的话,并不会引发任何的锁。

死锁

当L多个事务死锁的时候,即每个事务都在等待对方释放资源,因此这些事务都不能继续执行,这将导致MySQL无限期地挂起这些事务。

死锁等待的是界面一的事务结束,主动commit或者rollback带来的隐式commit或者重新begin,都可以结束事务。或者开启事务的线程丢失链接,这也会解开死锁状态。

索引

索引很重要,如果where里面涉及到没有索引的字段,那么行级锁就会变成全表锁。例如:id=1就是行锁,name='苏南大叔'就是表锁,不写where也是表锁!这个话题有些大,待后续文章更新。

终于找到能明显判断索引作用的地方了。哈哈!

参考:

结语

期待成功就需要耐得住寂寞,做好准备迎接机会的到来。苏南大叔的更多mysql经验文章,请点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   mysql