91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

數(shù)據(jù)庫(kù)的樂(lè)觀鎖和悲觀鎖的使用場(chǎng)景

電子工程師 ? 來(lái)源:ZYD ? 2019-02-25 11:04 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

在寫(xiě)入數(shù)據(jù)庫(kù)的時(shí)候需要有鎖,比如同時(shí)寫(xiě)入數(shù)據(jù)庫(kù)的時(shí)候會(huì)出現(xiàn)丟數(shù)據(jù),那么就需要鎖機(jī)制。

數(shù)據(jù)鎖分為樂(lè)觀鎖和悲觀鎖

它們使用的場(chǎng)景如下:

樂(lè)觀鎖適用于寫(xiě)少讀多的情景,因?yàn)檫@種樂(lè)觀鎖相當(dāng)于JAVA的CAS,所以多條數(shù)據(jù)同時(shí)過(guò)來(lái)的時(shí)候,不用等待,可以立即進(jìn)行返回。

悲觀鎖適用于寫(xiě)多讀少的情景,這種情況也相當(dāng)于JAVA的synchronized,reentrantLock等,大量數(shù)據(jù)過(guò)來(lái)的時(shí)候,只有一條數(shù)據(jù)可以被寫(xiě)入,其他的數(shù)據(jù)需要等待。執(zhí)行完成后下一條數(shù)據(jù)可以繼續(xù)。

他們實(shí)現(xiàn)的方式上有所不同。

樂(lè)觀鎖采用版本號(hào)的方式,即當(dāng)前版本號(hào)如果對(duì)應(yīng)上了就可以寫(xiě)入數(shù)據(jù),如果判斷當(dāng)前版本號(hào)不一致,那么就不會(huì)更新成功,

比如

update table set column = value

where version=${version} and otherKey = ${otherKey}

悲觀鎖實(shí)現(xiàn)的機(jī)制一般是在執(zhí)行更新語(yǔ)句的時(shí)候采用for update方式,

比如

update table set column='value'for update

這種情況where條件呢一定要涉及到數(shù)據(jù)庫(kù)對(duì)應(yīng)的索引字段,這樣才會(huì)是行級(jí)鎖,否則會(huì)是表鎖,這樣執(zhí)行速度會(huì)變慢。

下面我就弄一個(gè)spring boot(springboot 2.1.1 + mysql + lombok + aop + jpa)工程,然后逐漸的實(shí)現(xiàn)樂(lè)觀鎖和悲觀鎖。

假設(shè)有一個(gè)場(chǎng)景,有一個(gè)catalog商品目錄表,然后還有一個(gè)browse瀏覽表,假如一個(gè)商品被瀏覽了,那么就需要記錄下瀏覽的user是誰(shuí),并且記錄訪問(wèn)的總數(shù)。

表的結(jié)構(gòu)非常簡(jiǎn)單:

create table catalog (

id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',

name varchar(50) NOT NULL DEFAULT '' COMMENT '商品名稱',

browse_count int(11) NOT NULL DEFAULT 0 COMMENT '瀏覽數(shù)',

version int(11) NOT NULL DEFAULT 0 COMMENT '樂(lè)觀鎖,版本號(hào)',

PRIMARY KEY(id)

) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE table browse (

id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',

cata_id int(11) NOT NULL COMMENT '商品ID',

user varchar(50) NOT NULL DEFAULT '' COMMENT '',

create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',

PRIMARY KEY(id)

) ENGINE=INNODB DEFAULT CHARSET=utf8;

POM.XML的依賴如下:

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.1.1.RELEASE

com.hqs

dblock

1.0-SNAPSHOT

dblock

Demo project for Spring Boot

1.8

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-devtools

runtime

mysql

mysql-connector-java

runtime

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-starter-data-jpa

mysql

mysql-connector-java

org.projectlombok

lombok

true

org.aspectj

aspectjweaver

1.8.4

org.springframework.boot

spring-boot-maven-plugin

項(xiàng)目的結(jié)構(gòu)如下:

介紹一下項(xiàng)目的結(jié)構(gòu)的內(nèi)容:

entity包: 實(shí)體類包。

repository包:數(shù)據(jù)庫(kù)repository

service包: 提供服務(wù)的service

controller包: 控制器寫(xiě)入用于編寫(xiě)requestMapping。相關(guān)請(qǐng)求的入口類

annotation包: 自定義注解,用于重試。

aspect包: 用于對(duì)自定義注解進(jìn)行切面。

DblockApplication: springboot的啟動(dòng)類。

DblockApplicationTests: 測(cè)試類。

咱們看一下核心代碼的實(shí)現(xiàn),參考如下,使用dataJpa非常方便,集成了CrudRepository就可以實(shí)現(xiàn)簡(jiǎn)單的CRUD,非常方便,有興趣的同學(xué)可以自行研究。

實(shí)現(xiàn)樂(lè)觀鎖的方式有兩種:

1、更新的時(shí)候?qū)ersion字段傳過(guò)來(lái),然后更新的時(shí)候就可以進(jìn)行version判斷,如果version可以匹配上,那么就可以更新(方法:updateCatalogWithVersion)。

2、在實(shí)體類上的version字段上加入version,可以不用自己寫(xiě)SQL語(yǔ)句就可以它就可以自行的按照version匹配和更新,是不是很簡(jiǎn)單。

publicinterfaceCatalogRepositoryextendsCrudRepository {

@Query(value = "select * from Catalog a where a.id = :id for update", nativeQuery = true)

Optional findCatalogsForUpdate(@Param("id") Long id);

@Lock(value = LockModeType.PESSIMISTIC_WRITE) //代表行級(jí)鎖

@Query("select a from Catalog a where a.id = :id")

Optional findCatalogWithPessimisticLock(@Param("id") Long id);

@Modifying(clearAutomatically = true) //修改時(shí)需要帶上

@Query(value = "update Catalog set browse_count = :browseCount, version = version + 1 where id = :id " +

"and version = :version", nativeQuery = true)

int updateCatalogWithVersion(@Param("id") Long id, @Param("browseCount") Long browseCount, @Param("version") Long version);

}

實(shí)現(xiàn)悲觀鎖的時(shí)候也有兩種方式:

1、自行寫(xiě)原生SQL,然后寫(xiě)上for update語(yǔ)句。(方法:findCatalogsForUpdate)

2、使用@Lock注解,并且設(shè)置值為L(zhǎng)ockModeType.PESSIMISTIC_WRITE即可代表行級(jí)鎖。

還有我寫(xiě)的測(cè)試類,方便大家進(jìn)行測(cè)試:

package com.hqs.dblock;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.boot.test.web.client.TestRestTemplate;

import org.springframework.test.context.junit4.SpringRunner;

import org.springframework.util.LinkedMultiValueMap;

import org.springframework.util.MultiValueMap;

@RunWith(SpringRunner.class)

@SpringBootTest(classes = DblockApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

publicclassDblockApplicationTests {

@Autowired

privateTestRestTemplate testRestTemplate;

@Test

publicvoid browseCatalogTest() {

String url = "http://localhost:8888/catalog";

for(int i = 0; i < 100; i++) {

finalint num = i;

newThread(() -> {

MultiValueMap params = newLinkedMultiValueMap<>();

params.add("catalogId", "1");

params.add("user", "user" + num);

String result = testRestTemplate.postForObject(url, params, String.class);

System.out.println("-------------" + result);

}

).start();

}

}

@Test

publicvoid browseCatalogTestRetry() {

String url = "http://localhost:8888/catalogRetry";

for(int i = 0; i < 100; i++) {

finalint num = i;

newThread(() -> {

MultiValueMap params = newLinkedMultiValueMap<>();

params.add("catalogId", "1");

params.add("user", "user" + num);

String result = testRestTemplate.postForObject(url, params, String.class);

System.out.println("-------------" + result);

}

).start();

}

}

}

調(diào)用100次,即一個(gè)商品可以瀏覽一百次,采用悲觀鎖,catalog表的數(shù)據(jù)都是100,并且browse表也是100條記錄。采用樂(lè)觀鎖的時(shí)候,因?yàn)榘姹咎?hào)的匹配關(guān)系,那么會(huì)有一些記錄丟失,但是這兩個(gè)表的數(shù)據(jù)是可以對(duì)應(yīng)上的。

樂(lè)觀鎖失敗后會(huì)拋出ObjectOptimisticLockingFailureException,那么我們就針對(duì)這塊考慮一下重試,下面我就自定義了一個(gè)注解,用于做切面。

package com.hqs.dblock.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public@interfaceRetryOnFailure {

}

針對(duì)注解進(jìn)行切面,見(jiàn)如下代碼。我設(shè)置了最大重試次數(shù)5,然后超過(guò)5次后就不再重試。

package com.hqs.dblock.aspect;

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Pointcut;

import org.hibernate.StaleObjectStateException;

import org.springframework.orm.ObjectOptimisticLockingFailureException;

import org.springframework.stereotype.Component;

@Slf4j

@Aspect

@Component

publicclassRetryAspect {

publicstaticfinalint MAX_RETRY_TIMES = 5;//max retry times

@Pointcut("@annotation(com.hqs.dblock.annotation.RetryOnFailure)") //self-defined pointcount for RetryOnFailure

publicvoid retryOnFailure(){}

@Around("retryOnFailure()") //around can be execute before and after the point

publicObject doConcurrentOperation(ProceedingJoinPoint pjp) throwsThrowable {

int attempts = 0;

do {

attempts++;

try {

pjp.proceed();

} catch (Exception e) {

if(e instanceofObjectOptimisticLockingFailureException ||

e instanceofStaleObjectStateException) {

log.info("retrying....times:{}", attempts);

if(attempts > MAX_RETRY_TIMES) {

log.info("retry excceed the max times..");

throw e;

}

}

}

} while (attempts < MAX_RETRY_TIMES);

returnnull;

}

}

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴

原文標(biāo)題:聊聊數(shù)據(jù)庫(kù)樂(lè)觀鎖和悲觀鎖

文章出處:【微信號(hào):DBDevs,微信公眾號(hào):數(shù)據(jù)分析與開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    面試必看:排隊(duì)自旋之MCS的實(shí)現(xiàn)原理與關(guān)鍵考點(diǎn)

    在并發(fā)編程面試中,“” 是繞不開(kāi)的核心話題,而自旋作為輕量級(jí)的代表,其優(yōu)化方案更是高頻考點(diǎn)。
    的頭像 發(fā)表于 02-09 16:51 ?794次閱讀
    面試必看:排隊(duì)自旋<b class='flag-5'>鎖</b>之MCS<b class='flag-5'>鎖</b>的實(shí)現(xiàn)原理與關(guān)鍵考點(diǎn)

    智能指紋CW32系列有哪些應(yīng)用場(chǎng)景?

    智能指紋CW32系列有哪些應(yīng)用場(chǎng)景
    發(fā)表于 12-05 06:34

    國(guó)產(chǎn)數(shù)據(jù)庫(kù)的AI戰(zhàn)事

    國(guó)產(chǎn)數(shù)據(jù)庫(kù)硝煙再起,Vastbase V100構(gòu)筑企業(yè)智能基座
    的頭像 發(fā)表于 10-24 20:45 ?4197次閱讀
    國(guó)產(chǎn)<b class='flag-5'>數(shù)據(jù)庫(kù)</b>的AI戰(zhàn)事

    數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)—服務(wù)器異常斷電導(dǎo)致Oracle數(shù)據(jù)庫(kù)故障的數(shù)據(jù)恢復(fù)案例

    Oracle數(shù)據(jù)庫(kù)故障: 某公司一臺(tái)服務(wù)器上部署Oracle數(shù)據(jù)庫(kù)。服務(wù)器意外斷電導(dǎo)致數(shù)據(jù)庫(kù)報(bào)錯(cuò),報(bào)錯(cuò)內(nèi)容為“system01.dbf需要更多的恢復(fù)來(lái)保持一致性”。該Oracle數(shù)據(jù)庫(kù)
    的頭像 發(fā)表于 07-24 11:12 ?706次閱讀
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b><b class='flag-5'>數(shù)據(jù)</b>恢復(fù)—服務(wù)器異常斷電導(dǎo)致Oracle<b class='flag-5'>數(shù)據(jù)庫(kù)</b>故障的<b class='flag-5'>數(shù)據(jù)</b>恢復(fù)案例

    什么是電磁控制板?24路控板的使用步驟概述

    電磁控制板是一種專用于控制電磁工作狀態(tài)的電子裝置,它可以接收指令并對(duì)電磁進(jìn)行通斷電操作,從而實(shí)現(xiàn)對(duì)相關(guān)設(shè)備的鎖定和解鎖控制。電磁本身依靠電流產(chǎn)生磁場(chǎng)作用力來(lái)吸附或釋放
    的頭像 發(fā)表于 07-14 16:26 ?827次閱讀
    什么是電磁<b class='flag-5'>鎖</b>控制板?24路<b class='flag-5'>鎖</b>控板的使用步驟概述

    milvus向量數(shù)據(jù)庫(kù)的主要特性和應(yīng)用場(chǎng)景

    Milvus 是一個(gè)開(kāi)源的向量數(shù)據(jù)庫(kù),專門(mén)為處理和分析大規(guī)模向量數(shù)據(jù)而設(shè)計(jì)。它適用于需要高效存儲(chǔ)、檢索和管理向量數(shù)據(jù)的應(yīng)用場(chǎng)景,如機(jī)器學(xué)習(xí)、人工智能、計(jì)算機(jī)視覺(jué)和自然語(yǔ)言處理等。
    的頭像 發(fā)表于 07-04 11:36 ?1146次閱讀
    milvus向量<b class='flag-5'>數(shù)據(jù)庫(kù)</b>的主要特性和應(yīng)<b class='flag-5'>用場(chǎng)景</b>

    數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)—MongoDB數(shù)據(jù)庫(kù)文件丟失的數(shù)據(jù)恢復(fù)案例

    MongoDB數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)環(huán)境: 一臺(tái)操作系統(tǒng)為Windows Server的虛擬機(jī)上部署MongoDB數(shù)據(jù)庫(kù)。 MongoDB數(shù)據(jù)庫(kù)故障: 工作人員在MongoDB服務(wù)仍
    的頭像 發(fā)表于 07-01 11:13 ?691次閱讀
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b><b class='flag-5'>數(shù)據(jù)</b>恢復(fù)—MongoDB<b class='flag-5'>數(shù)據(jù)庫(kù)</b>文件丟失的<b class='flag-5'>數(shù)據(jù)</b>恢復(fù)案例

    數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)—SQL Server數(shù)據(jù)庫(kù)被加密如何恢復(fù)數(shù)據(jù)?

    SQL Server數(shù)據(jù)庫(kù)故障: SQL Server數(shù)據(jù)庫(kù)被加密,無(wú)法使用。 數(shù)據(jù)庫(kù)MDF、LDF、log日志文件名字被篡改。
    的頭像 發(fā)表于 06-25 13:54 ?745次閱讀
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b><b class='flag-5'>數(shù)據(jù)</b>恢復(fù)—SQL Server<b class='flag-5'>數(shù)據(jù)庫(kù)</b>被加密如何恢復(fù)<b class='flag-5'>數(shù)據(jù)</b>?

    離在線語(yǔ)音芯片WT2606A在智能行業(yè)的應(yīng)用場(chǎng)景

    離在線語(yǔ)音芯片 WT2606A 在智能行業(yè)的應(yīng)用場(chǎng)景主要圍繞語(yǔ)音交互升級(jí)、功能擴(kuò)展及用戶體驗(yàn)優(yōu)化展開(kāi),具體包括以下核心方向: 一、基礎(chǔ)語(yǔ)音提示與操作引導(dǎo) 開(kāi)鎖流程交互 用戶通過(guò)指紋、密碼或人臉識(shí)別
    的頭像 發(fā)表于 06-24 17:46 ?726次閱讀
    離在線語(yǔ)音芯片WT2606A在智能<b class='flag-5'>鎖</b>行業(yè)的應(yīng)<b class='flag-5'>用場(chǎng)景</b>

    一文讀懂Allegro先進(jìn)磁性開(kāi)關(guān)和存器

    Allegro 擁有豐富的霍爾效應(yīng)和隧道磁阻(TMR)開(kāi)關(guān)及存器產(chǎn)品,可廣泛應(yīng)用于汽車(chē)、工業(yè)和消費(fèi)電子等領(lǐng)域。本應(yīng)用筆記旨在提供分步選型流程,協(xié)助設(shè)計(jì)師為具體應(yīng)用場(chǎng)景選擇適配的 Allegro
    的頭像 發(fā)表于 06-12 17:26 ?1992次閱讀
    一文讀懂Allegro先進(jìn)磁性開(kāi)關(guān)和<b class='flag-5'>鎖</b>存器

    oracle數(shù)據(jù)恢復(fù)—oracle數(shù)據(jù)庫(kù)誤執(zhí)行錯(cuò)誤truncate命令如何恢復(fù)數(shù)據(jù)?

    oracle數(shù)據(jù)庫(kù)誤執(zhí)行truncate命令導(dǎo)致數(shù)據(jù)丟失是一種常見(jiàn)情況。通常情況下,oracle數(shù)據(jù)庫(kù)誤操作刪除數(shù)據(jù)只需要通過(guò)備份恢復(fù)數(shù)據(jù)
    的頭像 發(fā)表于 06-05 16:01 ?1403次閱讀
    oracle<b class='flag-5'>數(shù)據(jù)</b>恢復(fù)—oracle<b class='flag-5'>數(shù)據(jù)庫(kù)</b>誤執(zhí)行錯(cuò)誤truncate命令如何恢復(fù)<b class='flag-5'>數(shù)據(jù)</b>?

    MySQL數(shù)據(jù)庫(kù)采集網(wǎng)關(guān)是什么?有什么功能?

    MySQL數(shù)據(jù)庫(kù)采集網(wǎng)關(guān)是一種用于連接、采集、處理并傳輸數(shù)據(jù)到MySQL數(shù)據(jù)庫(kù)的中間設(shè)備或軟件系統(tǒng),通常部署在數(shù)據(jù)源與MySQL數(shù)據(jù)庫(kù)之間,
    的頭像 發(fā)表于 05-26 15:20 ?721次閱讀

    SQLSERVER數(shù)據(jù)庫(kù)是什么

    SQL Server 是由微軟公司開(kāi)發(fā)的一款 關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDBMS) ,用于存儲(chǔ)、管理和檢索結(jié)構(gòu)化數(shù)據(jù)。它是企業(yè)級(jí)應(yīng)用中廣泛使用的數(shù)據(jù)庫(kù)解決方案之一,尤其適用于Windows平臺(tái),但也
    的頭像 發(fā)表于 05-26 09:19 ?1223次閱讀

    MySQL數(shù)據(jù)庫(kù)是什么

    開(kāi)發(fā)、企業(yè)應(yīng)用和大數(shù)據(jù)場(chǎng)景。以下是其核心特性和應(yīng)用場(chǎng)景的詳細(xì)說(shuō)明: 核心特性 關(guān)系型數(shù)據(jù)庫(kù)模型 數(shù)據(jù)以 表(Table) 形式組織,表由行(
    的頭像 發(fā)表于 05-23 09:18 ?1301次閱讀

    數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)——MongoDB數(shù)據(jù)庫(kù)文件拷貝后服務(wù)無(wú)法啟動(dòng)的數(shù)據(jù)恢復(fù)

    MongoDB數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)環(huán)境: 一臺(tái)Windows Server操作系統(tǒng)虛擬機(jī)上部署MongoDB數(shù)據(jù)庫(kù)。 MongoDB數(shù)據(jù)庫(kù)故障: 管理員在未關(guān)閉MongoDB服務(wù)的
    的頭像 發(fā)表于 04-09 11:34 ?917次閱讀
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b><b class='flag-5'>數(shù)據(jù)</b>恢復(fù)——MongoDB<b class='flag-5'>數(shù)據(jù)庫(kù)</b>文件拷貝后服務(wù)無(wú)法啟動(dòng)的<b class='flag-5'>數(shù)據(jù)</b>恢復(fù)