MyBatis-Plusは楽観的ロックを実装します
オプティミスティックロックはペシミスティックロックに関連しています。オプティミスティックロックは、データが一般に競合を引き起こさないことを前提としているため、データが送信および更新されると、データの競合が正式に検出されます。競合が見つかった場合は、ユーザーが間違ったものを返すようにします。情報、ユーザーに何をすべきかを決定させます。
役割:オプティミスティックロックは、並行プロセスでのデータ更新の競合の問題を解決することです。オプティミスティックロックは、並行プロセスでのプログラムスループットを向上させることができます。
1.バージョン番号管理
楽観的ロックは、バージョンレコードメカニズムを使用して実装されます。これは、楽観的ロックの最も一般的に使用される実装です。データバージョンとは何ですか?データバージョンとは、具体的にはデータにバージョン識別子を追加することを指します。通常、データベーステーブルに数値の「バージョン」フィールドを追加することで実現されます。データを読み取るときは、バージョンフィールドの値が一緒に読み取られ、データが読み込まれます。は毎回更新されます。、バージョンは1ずつ増加します。更新を送信するときは、データベーステーブル内の対応するレコードの現在のバージョン情報を、最初に取得したバージョン値と比較します。データレコードの現在のバージョン番号が、最初に取得したバージョン値と等しい場合は、それ以外の場合は、期限切れのデータと見なされ、更新されません。
上図のように、更新操作を順次実行すると、データのバージョンが順次インクリメントされ、競合は発生しません。ただし、同じバージョンのデータを変更するさまざまなビジネスオペレーションがある場合、最初に送信された操作(図のB)はデータバージョンを2に更新します。AがBの後に更新を送信すると、データが変更された場合、Aの更新操作は失敗します。
2.楽観的ロックを実装する方法は?
@Version
アノテーションは楽観的ロックを示し、バージョンフィールドはデータのセキュリティを確保するために使用されます。データを変更する場合、バージョンは条件として使用され、条件が確立された場合にのみ変更が成功します。
- レコードをフェッチするときは、現在のバージョンを取得します
- 更新するときは、このバージョンを持参してください
- 更新を実行する場合、
update tableName set version = oldVersion + 1 where version = oldVersion
- バージョンが間違っている場合、更新は失敗します
1.バージョンフィールドをデータベーステーブルに追加し、デフォルト値を1に設定します。
MySQL-ユーザーデータテーブルの情報は次のとおりです。
2.バージョン属性をエンティティクラスに追加し、@Version
注釈ます;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String name;
private Integer age;
private String email;
//乐观锁
@Version
private Integer version;
//字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
3.構成クラス(コンポーネント)を登録します。
//扫描我们的repository文件夹
@MapperScan("com.trainingl.repository")
@EnableTransactionManagement
@Configuration //配置类
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//注册乐观锁插件
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
4.楽観的ロックをテストします。
// 测试乐观锁成功
@Test
public void testOptimisticLock(){
//修改用户信息时,先查询用户信息,再进行修改
//1. 查询用户信息
User user = userMapper.selectById(1L);
//2. 修改用户信息
user.setName("zhangsan");
user.setAge(36);
user.setEmail("[email protected]");
//3. 执行更新操作
userMapper.updateById(user);
}
これは、コンソールのログ情報から検出されます。データを変更する場合、バージョンは条件付き判断として使用され、バージョンは自動的に自動インクリメント操作を完了します。つまり、次のようになりversion = version+1
ます。
// 测试多线程下乐观锁失败
@Test
public void testOptimisticLock1(){
//线程 1
User user1 = userMapper.selectById(1L);
user1.setName("zhangshan");
user1.setEmail("[email protected]");
//线程 2(在线程1的修改操作未来得及执行时介入)
User user2 = userMapper.selectById(1L);
user2.setName("kuangsan");
user2.setEmail("[email protected]");
userMapper.updateById(user2);
//如果没有乐观锁就会覆盖插队线程的值!
userMapper.updateById(user1); //更新失败
}
スレッド1のログ情報(更新に成功):
スレッド2のログ情報(更新に失敗しました):
オプティミスティックロックは、読み取りが多く書き込みが少ないシナリオに適しており、プログラムのスループットを向上させることができます。楽観的同時実行制御は、トランザクション間のデータ競合の可能性が比較的小さいと考えているため、可能な限り直接実行し、コミット時までロックしないでください。