• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    MySQL 加锁控制并发的方法

    前言

    锁总体可以分为乐观锁和悲观锁,简单说,乐观锁用版本号控制,悲观锁用锁控制。

    下面是待会要用来测试的数据

    # 添加一个user表
    CREATE TABLE `users` (
     `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
     `name` varchar(255) NOT NULL COMMENT '姓名',
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
    # 插入3条数据
    INSERT INTO `users` (`id`, `name`)
    VALUES
     (1, '雪山飞猪'),
     (2, 'chenqionghe'),
     (3, 'cqh');

    查询结果如下:

    一、乐观锁

    核心原理是增加一个version的字段来控制。
    举个场景,我们希望并发更新单行记录的时候的时候,只有一个进程更新成功,如下

    UPDATE users SET name="雪山飞猪" WHERE id=3
    UPDATE users SET name="chenqionghe" WHERE id=3

    上面这两个sql最终都会更新成功,且以最后更新结果为主。

    解决办法是添加一个version字段

    添加version字段

    ALTER TABLE users ADD `version` INT NOT NULL DEFAULT '0'

    解决办法是添加一个version字段,每个更新时where条件都加上它,并且也更新它

    UPDATE users SET name="雪山飞猪",version=version+1 WHERE id=3 AND version=0
    UPDATE users SET name="chenqionghe",version=version+1 WHERE id=3 AND version=0

    这次变成了只会更新成功一次,谁先抢到这条记录以谁为主,因为当前一个进程更新成功后版本号已经变化了,第二个进程找不到这条记录了。
    这就是最简单的CAS机制。

    二、悲观锁

    其实类似Go语言里的Mutex和RwMutex读锁

    读锁

    也叫共享锁或S锁,当给数据表加上共享锁的时候,表就变成了只读模式。
    我们可以锁全表,也可以锁全表或部分行,如下

    全表锁(LOCK TABLE 表 READ)

    语法如下

    LOCK TABLE 表 READ
    UNLOCK TABLE;

    我们来测试一个,第一个进程执行

    LOCK TABLE users READ;

    第二个进程执行正常读

    SELECT * FROM users WHERE id=1;

    可以正常查询。我们再来执行一下更新

    UPDATE users SET name="chenqionghe" WHERE id=1

    出现了等待。

    我们给第一个进程解锁

    再看第二个进程,已经更新成功

    行锁(SELECT ... LOCK IN SHARE MODE)

    BEGIN;
    SELECT * FROM users WHERE id IN (1,2) LOCK IN SHARE MODE
    COMMIT;

    必须配合事务使用,BEIN开始后,锁定的行,外部只能查询,不能更新

    我们来测试一下,第一个进程执行

    BEGIN;
    SELECT * FROM users WHERE id IN (1,2) LOCK IN SHARE MODE

    这里锁定了id为1和2的记录行。我们第二个进程执行更新

    UPDATE users SET name="雪山飞猪" WHERE id=1

    又一次出现了等待。
    好,这时候我们将第一个进程的事务提交

    COMMIT;

    第二个进程更新成功了,如下

    写锁

    也排他锁、独占锁,理解成读和写都不行了,语法如下

    全表锁(LOCK TABLE 表 WRITE)

    LOCK TABLE users WRITE;

    这时候已经锁定全表,我们再用另一个进程查询一下id为1的数据

    SELECT * FROM users WHERE id=1

    可以看到,查询已经发生了等待。
    我们再将第一个进程解锁

    UNLOCK TABLE

    这时候,第二个进程立马查询成功

    行锁(SELECT ... FOR UPDATE)

    当我们对数据进行更新的时候(INSERT、DELETE、UPDATE)的时候,数据库会自动使用排它锁,防止其他事务操作该数据

    BEGIN;
    SELECT * FROM users WHERE id IN (1,2) LOCK IN SHARE MODE
    COMMIT;

    我们再来测试一下,第一个进程锁定id为1和2的记录

    BEGIN;
    SELECT * FROM users WHERE id IN (1,2) FOR UPDATE

    注意:这时候事务没提交

    我们先用第二个进程来更新id为3的记录(未被锁定)

    UPDATE users SET name="chenqionghe" WHERE id=3

    执行成功了。
    我们再来更新一个id为1的记录

    UPDATE users SET name="chenqionghe" WHERE id=1

    发生了等待,说明已经被锁定了。
    好,我们提交第一个进程的事务

    COMMIT;

    再去看第二个进程,已经更新成功

    简单说乐观锁用version控制,悲观锁的表锁一般用不着,行的读锁用LOCK IN SHARE MODE,写锁用FRO UPDATE,就是这么简单!

    以上就是MySQL 加锁控制并发的方法的详细内容,更多关于MySQL 加锁控制并发的资料请关注脚本之家其它相关文章!

    您可能感兴趣的文章:
    • MySQL出现Waiting for table metadata lock的原因方法
    • MySQL表结构变更你不可不知的Metadata Lock详解
    • MYSQL METADATA LOCK(MDL LOCK)MDL锁问题分析
    • MySQL slave 延迟一列 外键检查和自增加锁
    • 浅谈MySQL next-key lock 加锁范围
    • PHP+MySQL高并发加锁事务处理问题解决方法
    • MYSQL METADATA LOCK(MDL LOCK) 理论及加锁类型测试
    上一篇:MySQL 8.0.23中复制架构从节点自动故障转移的问题
    下一篇:mysql 使用B+树索引有哪些优势
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    MySQL 加锁控制并发的方法 MySQL,加锁,控制,并发,的,