文章目录
  1. 1. 文档更新说明
  2. 2. 前言
  3. 3. 共享锁,排他锁
  4. 4. 两种锁的作用
  5. 5. 创建一个用于测试的表
  6. 6. 使用写锁的效果
    1. 6.0.1. 测试读锁
      1. 6.0.1.1. case1
      2. 6.0.1.2. case2
    2. 6.0.2. 测试写锁
      1. 6.0.2.1. case1
    3. 6.0.3. 补充说明

文档更新说明

  • 最后更新 2018年04月27日
  • 首次更新 2018年04月27日

前言

  忽然想起了去年在项目的并发处理中遇到了一次更新丢失的问题, 感觉最近又可能会接触到这部分开发, 赶紧整理一下资料学习学习~   

共享锁,排他锁

  数据库领域里边好好几种锁,本文只针对两种锁来讲.共享锁又称读锁,排他锁又称写锁.锁有表锁和行锁,本文只针对事务里的行锁.
  MySQL事务中,行锁有两个语法

select *** lock in share mode 这个是设置共享锁(读锁)
select *** for update 这个是设置读锁排他锁(写锁)

  

两种锁的作用

  1. 加共享锁, 允许其他进程跟着加共享锁, 但是其他进程修改数据会堵塞, 其他进程加排他锁也会堵塞.
  2. 加排他锁, 允许其他进程直接读数据, 但是不允许其他进程加共享锁 or 加排他锁.当然也不允许其他进程修改数据.

其实解决我遇到的更新丢失问题,用排他锁就可以解决了.我有多个事务同时读取,并准备修改数据.只需要保证读取的时候加了排他锁,这样其他事务就无法在加排他锁的情况下读取了.这样就避免了更新丢失问题了.

创建一个用于测试的表

CREATE TABLE `user_charge` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `user_id` varchar(255) DEFAULT NULL,
    `llt_in` bigint(20) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`),
    UNIQUE KEY `user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1;

  其中的llt_in, 就是我们的要用来修改的字段.(不要纠结名字,我只是直接把项目的数据表复制出来修改而已😌.)

使用写锁的效果

测试读锁

case1

  打开终端, 进入mysql,开始我们的效果演示.
session1:

set autocommit = 0;
begin; //开启事务
select * from user_charge where user_id = 1 lock in share mode\G;

session2:

select * from user_charge where user_id = 1 lock in share mode\G;

此时session2可以直接顺利读取.说明同一行的共享锁可以在多个进程中添加.

case2

  接着上面的情况继续.
session2:

select * from user_charge where user_id = 1 for update; 
#或者执行下面一行
update user_charge SET llt_in = 6 where user_id = 1;

此时发现这行执行之后session2堵塞了. 所以,一个事务加了共享锁之后, 其他进程如果要加排他锁或者修改数据,都会堵塞.

测试写锁

case1

session1:

set autocommit = 0;
begin; #开启事务
select * from user_charge where user_id = 1 for update;

session2:

#select * from user_charge where user_id = 1; #提示: 直接读取是没问题的
select * from user_charge where user_id = 1 lock in share mode;
#或者执行下一行
select * from user_charge where user_id = 1 for update;

此时发现这行执行之后session2堵塞了. 所以,一个事务加了排他锁之后,其他进程如果要加共享锁或者排他锁都是不行的,当然修改就更不行了,你可以自己试试~

补充说明

  上面例子没有说怎么解除堵塞,其实很简单,只要有锁的进程执行commit,就可以释放锁了,其他进程就不会堵塞了.

文章目录
  1. 1. 文档更新说明
  2. 2. 前言
  3. 3. 共享锁,排他锁
  4. 4. 两种锁的作用
  5. 5. 创建一个用于测试的表
  6. 6. 使用写锁的效果
    1. 6.0.1. 测试读锁
      1. 6.0.1.1. case1
      2. 6.0.1.2. case2
    2. 6.0.2. 测试写锁
      1. 6.0.2.1. case1
    3. 6.0.3. 补充说明