> 데이터 베이스 > MySQL 튜토리얼 > mysql 낙관적 잠금이란 무엇입니까?

mysql 낙관적 잠금이란 무엇입니까?

coldplay.xixi
풀어 주다: 2020-06-29 15:56:42
원래의
4793명이 탐색했습니다.

mysql 낙관적 잠금은 비관적 잠금과 비교됩니다. 낙관적 잠금은 일반적인 상황에서는 데이터가 충돌을 일으키지 않는다고 가정합니다. 따라서 업데이트를 위해 데이터를 제출하면 충돌이 발견되면 공식적으로 감지됩니다. 그런 다음 사용자에게 오류 정보를 반환하고 사용자가 무엇을 할지 결정하도록 합니다.

mysql 낙관적 잠금이란 무엇입니까?

mysql 낙관적 잠금은 (Optimistic Locking) 비관적 잠금과 비교하여 낙관적 잠금은 정상적인 상황에서는 데이터가 충돌을 일으키지 않을 것이라고 가정하므로 데이터가 제출되고 업데이트될 때 데이터가 공식적으로 업데이트됩니다. 충돌이 있는지 확인합니다. 충돌이 발견되면 오류 정보가 사용자에게 반환되고 사용자는 무엇을 할지 결정할 수 있습니다.

그러면 낙관적 잠금을 어떻게 구현합니까? 일반적으로 두 가지 방법이 있습니다.

1 데이터 버전(버전) 기록 메커니즘을 사용하여 가장 일반적으로 사용되는 낙관적 잠금 구현 방법입니다. 데이터 버전이란 무엇입니까? 이는 일반적으로 데이터베이스 테이블에 숫자 "버전" 필드를 추가하여 데이터에 버전 식별자를 추가하는 것입니다. 데이터를 읽을 때 버전 필드의 값을 함께 읽어 데이터가 업데이트될 때마다 버전 값이 1씩 증가합니다.

업데이트를 제출할 때 데이터베이스 테이블의 해당 레코드의 현재 버전 정보를 처음 가져온 버전 값과 비교합니다. 데이터베이스 테이블의 현재 버전 번호가 가져온 버전 값과 같습니다. 처음으로 업데이트되면 업데이트되고, 그렇지 않으면 만료된 데이터로 간주됩니다. 다음 그림을 사용하여 설명합니다.

mysql 낙관적 잠금이란 무엇입니까?

위 그림과 같이 업데이트 작업이 순차적으로 수행되면 데이터 버전이 충돌 없이 순차적으로 증가합니다. 그러나 서로 다른 비즈니스 운영이 동일한 버전의 데이터를 수정하는 경우 먼저 제출된 작업(그림의 B)은 데이터 버전을 2로 업데이트합니다. A가 B 이후에 업데이트를 제출하면 데이터 버전이 수정된 것으로 확인됩니다. . 이면 A의 업데이트 작업이 실패합니다.

2. 낙관적 잠금의 두 번째 구현 방법은 첫 번째와 유사합니다. 또한 낙관적 잠금 제어가 필요한 필드를 추가합니다. 필드 유형은 유사합니다. 위 버전에서는 업데이트가 제출되면 현재 데이터베이스에 있는 데이터의 타임스탬프를 확인하고 업데이트 전에 얻은 타임스탬프와 비교합니다. 일치하면 괜찮습니다. 그렇지 않으면 버전 충돌입니다.

관련 학습 권장 사항:

mysql 비디오 튜토리얼

사용 예:

MySQL InnoDB를 예로 들어

MySQL InnoDB为例

还是拿之前的实例来举:商品goods表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单,那么我们对某个商品下单时必须确保该商品status为1。假设商品的id为1。

下单操作包括3步骤:

1、查询出商品信息

select (status,status,version) from t_goods where id=#{id}
로그인 후 복사

2、根据商品信息生成订单

3、修改商品status为2

update t_goods 
set status=2,version=version+1
where id=#{id} and version=#{version};
로그인 후 복사

那么为了使用乐观锁,我们首先修改t_goods表,增加一个version字段,数据默认version值为1。

t_goods表初始数据如下:

mysql> select * from t_goods;  
+----+--------+------+---------+  
| id | status | name | version |  
+----+--------+------+---------+  
|  1 |      1 | 道具 |       1 |  
|  2 |      2 | 装备 |       2 |  
+----+--------+------+---------+  
2 rows in set  
  
mysql>
로그인 후 복사

对于乐观锁的实现,我使用MyBatis来进行实践,具体如下:

Goods实体类:

/** 
 * ClassName: Goods <br/> 
 * Function: 商品实体. <br/> 
 * date: 2013-5-8 上午09:16:19 <br/> 
 * @author chenzhou1025@126.com 
 */  
public class Goods implements Serializable {  
  
    /** 
     * serialVersionUID:序列化ID. 
     */  
    private static final long serialVersionUID = 6803791908148880587L;  
      
    /** 
     * id:主键id. 
     */  
    private int id;  
      
    /** 
     * status:商品状态:1未下单、2已下单. 
     */  
    private int status;  
      
    /** 
     * name:商品名称. 
     */  
    private String name;  
      
    /** 
     * version:商品数据版本号. 
     */  
    private int version;  
      
    @Override  
    public String toString(){  
        return "good id:"+id+",goods status:"+status+",goods name:"+name+",goods version:"+version;  
    }  
  
    //setter and getter  
  
}
로그인 후 복사

GoodsDao

/** 
 * updateGoodsUseCAS:使用CAS(Compare and set)更新商品信息. <br/> 
 * 
 * @author chenzhou1025@126.com 
 * @param goods 商品对象 
 * @return 影响的行数 
 */  
int updateGoodsUseCAS(Goods goods);
로그인 후 복사

mapper.xml

<update id="updateGoodsUseCAS" parameterType="Goods">  
    <![CDATA[ 
        update t_goods 
        set status=#{status},name=#{name},version=version+1 
        where id=#{id} and version=#{version} 
    ]]>  
</update>
로그인 후 복사

GoodsDaoTest测试类

@Test  
public void goodsDaoTest(){  
    int goodsId = 1;  
    //根据相同的id查询出商品信息,赋给2个对象  
    Goods goods1 = this.goodsDao.getGoodsById(goodsId);  
    Goods goods2 = this.goodsDao.getGoodsById(goodsId);  
      
    //打印当前商品信息  
    System.out.println(goods1);  
    System.out.println(goods2);  
      
    //更新商品信息1  
    goods1.setStatus(2);//修改status为2  
    int updateResult1 = this.goodsDao.updateGoodsUseCAS(goods1);  
    System.out.println("修改商品信息1"+(updateResult1==1?"成功":"失败"));  
      
    //更新商品信息2  
    goods1.setStatus(2);//修改status为2  
    int updateResult2 = this.goodsDao.updateGoodsUseCAS(goods1);  
    System.out.println("修改商品信息2"+(updateResult2==1?"成功":"失败"));  
}
로그인 후 복사

输出结果:

good id:1,goods status:1,goods name:道具,goods version:1  
good id:1,goods status:1,goods name:道具,goods version:1  
修改商品信息1成功  
修改商品信息2失败
로그인 후 복사

说明:

GoodsDaoTest测试方法中,我们同时查出同一个版本的数据,赋给不同的goods对象,然后先修改good1对象然后执行更新操作,执行成功。然后我们修改goods2,执行更新操作时提示操作失败。此时t_goods이전 예를 들어보겠습니다. 상품에 제품이 있습니다. 테이블 필드 상태에서 상태 1은 제품이 주문되지 않았음을 의미하고, 상태 2는 제품이 주문되었음을 의미합니다. 그러면 특정 제품을 주문할 때 제품의 상태를 확인해야 합니다. 1입니다. 제품 ID가 1이라고 가정합니다.

주문 작업은 3단계로 구성됩니다.

🎜1. 상품 정보 조회🎜
mysql> select * from t_goods;  
+----+--------+------+---------+  
| id | status | name | version |  
+----+--------+------+---------+  
|  1 |      2 | 道具 |       2 |  
|  2 |      2 | 装备 |       2 |  
+----+--------+------+---------+  
2 rows in set  
  
mysql>
로그인 후 복사
🎜2. 상품 정보를 기반으로 주문을 생성합니다.🎜🎜3. 상품 상태를 2🎜
update t_goods   
set status=2,version=version+1  
where id=#{id} and version=#{version};
로그인 후 복사
🎜🎜🎜로 수정합니다. 낙관적 잠금을 사용하려면 먼저 t_goods 테이블을 수정하고 버전 필드를 추가합니다. 데이터의 기본 버전 값은 1입니다. 🎜🎜t_goods 테이블의 초기 데이터는 다음과 같습니다. 🎜rrreee🎜낙관적 잠금 구현을 위해 MyBatis를 사용하여 연습합니다. 🎜🎜🎜Goods 엔터티 클래스: 🎜🎜rrreee🎜 🎜GoodsDao🎜🎜rrreee 🎜🎜mapper.xml🎜🎜rrreee🎜🎜GoodsDaoTest 테스트 클래스 🎜🎜rrreee🎜출력 결과: 🎜rrreee🎜🎜설명: 🎜🎜🎜GoodsDaoTest 코드> 테스트 방법에서 우리는 동일한 버전과 동시에 다른 상품 개체에 데이터를 할당한 후 good1 개체를 먼저 수정한 후 업데이트 작업을 수행하여 실행이 성공합니다. 그런 다음 good2를 수정하고 업데이트 작업을 수행할 때 작업이 실패했다는 메시지가 표시됩니다. 이때 <code>t_goods 테이블의 데이터는 다음과 같습니다. 🎜rrreee🎜 첫 번째 업데이트에서 ID가 1인 데이터 버전이 2로 수정된 것을 확인할 수 있습니다. 따라서 good2를 업데이트하면 조건이 더 이상 일치하지 않으므로 업데이트가 성공하지 못합니다. 구체적인 SQL은 다음과 같습니다. 🎜rrreee🎜이 방법으로 낙관적 잠금을 달성했습니다. 🎜

위 내용은 mysql 낙관적 잠금이란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿