最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SELECT… FOR UPDATE 排他鎖的實現(xiàn)

 更新時間:2023年01月12日 11:25:42   作者:我是最菜程序員  
本文主要介紹了SELECT… FOR UPDATE 排他鎖的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1. SELECT…FOR UPDATE 是什么?作用是什么?

select for update 即排他鎖,排他鎖又稱為寫鎖,簡稱X鎖,顧名思義,排他鎖就是不能與其他鎖并存,如一個事務(wù)獲取了一個數(shù)據(jù)行的排他鎖,其他事務(wù)就不能再獲取該行的其他鎖,包括共享鎖和排他鎖,但是獲取排他鎖的事務(wù)是可以對數(shù)據(jù)就行讀取和修改。

作用:保證數(shù)據(jù)的一致性,為了在查詢時,避免其他用戶對該表進行插入,修改或刪除等操作,造成表數(shù)據(jù)的不一致性。

2. MYSQL中如何查詢是否存在鎖信息?相關(guān)SQL

這里只講述和排他鎖有關(guān)內(nèi)容。

2.1MYSQL INFORMATION_SCHEMA 數(shù)據(jù)庫

INFORMATION_SCHEMA 是mysql自帶的元數(shù)據(jù)數(shù)據(jù)庫INNODB_TRX是MYSQL中事務(wù)和鎖相關(guān)的表INNODB_TRX表提供了當(dāng)前INNODB引擎內(nèi)每個事務(wù)的信息(除只讀事務(wù)外),包括當(dāng)一個事務(wù)啟動,事務(wù)是否在等待一個鎖,以及正在執(zhí)行的SQL語句。
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

3. SELECT…FOR UPDATE 怎么使用?如何驗證?

這里使用mysql數(shù)據(jù)庫為例。

3.1 Mysql Config表SQL

-- ----------------------------
-- Table structure for config
-- ----------------------------
DROP TABLE IF EXISTS `config`;
CREATE TABLE `config`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `value` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `name-index`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of config
-- ----------------------------
INSERT INTO `config` VALUES (1, 'result', 'false');

3.2 創(chuàng)建SpringBoot工程,結(jié)構(gòu)目錄如下

├─main
│  ├─java
│  │  └─com
│  │      └─xy
│  │          └─springboot
│  │              │  Application.java
│  │              ├─db
│  │              │  ├─dao
│  │              │  │  │  ConfigDao.java
│  │              │  │  ├─impl
│  │              │  │  │      ConfigDaoImpl.java
│  │              │  │  └─mapper
│  │              │  │          ConfigMapper.java
│  │              │  └─entity
│  │              │          Config.java
│  │              └─runner
│  │                      ExclusiveLocksRunner.java
│  └─resources
│      │  application.properties
│      └─Mapper
└─              ConfigMapper.xml

3.2 pom.xml文件內(nèi)容

引入mysql driver、lombok、mybatis-plus等依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xy</groupId>
    <artifactId>spring-boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
		<!-- 使用mybatis-plus 持久層框架 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!-- mysql 連接驅(qū)動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.4 db層接口及其實現(xiàn)類

Mapper映射xml文件內(nèi)容如下:ConfigMapper.xml

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xy.springboot.db.dao.mapper.ConfigMapper">
    <select id="getLockedConfig" resultType="com.xy.springboot.db.entity.Config">
        SELECT
        *
        FROM CONFIG
        WHERE name = #{name} AND value = ${value}
        FOR UPDATE SKIP LOCKED
    </select>
</mapper>

ConfigMapper.java 接口類

package com.xy.springboot.db.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xy.springboot.db.entity.Config;
import org.apache.ibatis.annotations.Param;

public interface ConfigMapper extends BaseMapper<Config> {
    Config getLockedConfig(@Param("name") String name, @Param("value") String value);
}

ConfigDao.java 接口類及其實現(xiàn)類

package com.xy.springboot.db.dao;

import com.baomidou.mybatisplus.extension.service.IService;
import com.xy.springboot.db.entity.Config;

/**
 * 配置類接口
 */
public interface ConfigDao extends IService<Config> {

    /**
     * 通過名稱和value值,獲取增加排他鎖的配置
     * @param name
     * @param value
     */
    Config getLockedConfig(String name, String value);
}

package com.xy.springboot.db.dao.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xy.springboot.db.dao.ConfigDao;
import com.xy.springboot.db.dao.mapper.ConfigMapper;
import com.xy.springboot.db.entity.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ConfigDaoImpl extends ServiceImpl<ConfigMapper, Config> implements ConfigDao {
    private ConfigMapper configMapper;

    @Autowired
    public void setConfigMapper(ConfigMapper configMapper) {
        this.configMapper = configMapper;
    }

    @Override
    public Config getLockedConfig(String name, String value) {
        return configMapper.getLockedConfig(name, value);
    }
}

Config.java 實體類

package com.xy.springboot.db.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;

/**
 * 配置表實體類
 */
@TableName("config")
@Getter
@Setter
public class Config {

    private int id;

    private String name;

    private String value;
}

3.5 Application.java 開啟Mapper掃描和開啟事務(wù)

package com.xy.springboot;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@MapperScan(basePackages = "com.xy.springboot.db.dao.mapper")
@EnableTransactionManagement
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3.6 [核心] ExclusiveLocksRunner 排他鎖Runner

ExclusiveLocksRunner 該類實現(xiàn)了ApplicationRunner接口,其含義是在SpringBoot工程啟動之后,執(zhí)行的操作。該類必須注入到IOC容器中。
package com.xy.springboot.runner;

import com.xy.springboot.db.dao.ConfigDao;
import com.xy.springboot.db.entity.Config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 排他鎖驗證
 */
@Slf4j
@Component
public class ExclusiveLocksRunner implements ApplicationRunner {

    private static final String RESULT_KEY = "result";
    private static final String RESULT = "false";

    private ConfigDao configDao;

    @Autowired
    public void setConfigDao(ConfigDao configDao) {
        this.configDao = configDao;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void run(ApplicationArguments args) throws Exception {
        Config lockedConfig = configDao.getLockedConfig(RESULT_KEY, RESULT);
        if (lockedConfig == null) {
            log.error("config is null。because config is locked.");
            return;
        }
        log.info("start doing");
        lockedConfig.setValue("true");
        configDao.updateById(lockedConfig);
    }
}

3.7 疑問&并驗證

疑問:

  • ExclusiveLocksRunner類中run方法上的@Transactional 注解是否起作用?
  • select…for update 是否有效?
  • select…for update 加鎖之后,未釋放之前,再次加鎖時,返回的lockedConfig內(nèi)容是什么?

斷點位置:

  • 事務(wù)攔截器(使用AOP的方式對@Transactional注解進行處理)inovke方法處斷點: org.springframework.transaction.interceptor.TransactionInterceptor#invoke
  • ExclusiveLocksRunner.java run 方法

Debug如圖所示,證明ExclusiveLocksRunner.java中run 方法上@Transcational 注解是有效的。

進入invokeWithinTransaction 調(diào)用事務(wù)方法繼續(xù)調(diào)試,

整個調(diào)用流程如下:創(chuàng)建事務(wù)——> 調(diào)用run方法 -> commit提交事務(wù)。

進入run方法:根據(jù)檢索條件查詢內(nèi)容,并對其內(nèi)容設(shè)置類排他鎖。

LOG信息如下:

查詢mysql中是否存在對應(yīng)的排他鎖信息

-- 執(zhí)行如下信息,查看是否存在Lock信息
SELECT trx_id, trx_state, trx_started, trx_rows_locked  FROM INFORMATION_SCHEMA.INNODB_TRX;

結(jié)果如下:

證明:數(shù)據(jù)庫中已經(jīng)存在排他鎖信息,證明該加鎖方式是OK的,并在大概在第2行。

在數(shù)據(jù)庫中,再次執(zhí)行以下SQL,進行查詢,得到結(jié)果為null。證書排他鎖未釋放之前,再次枷鎖時,返回內(nèi)容為null,因此select…for update 加鎖之后,未釋放之前,再次加鎖時,返回的lockedConfig內(nèi)容時null。

 到此這篇關(guān)于SELECT… FOR UPDATE 排他鎖的實現(xiàn)的文章就介紹到這了,更多相關(guān)SELECT… FOR UPDATE 排他鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL性能分析工具profile使用教程

    MySQL性能分析工具profile使用教程

    這篇文章主要介紹了MySQL性能分析工具profile使用教程,本文描述了如何使用MySQL profile,不涉及具體的樣例分析,需要的朋友可以參考下
    2014-10-10
  • MYSQL 的10大經(jīng)典優(yōu)化案例場景實戰(zhàn)

    MYSQL 的10大經(jīng)典優(yōu)化案例場景實戰(zhàn)

    在應(yīng)用開發(fā)的早期,數(shù)據(jù)量少,開發(fā)人員開發(fā)功能時更重視功能上的實現(xiàn),隨著生產(chǎn)數(shù)據(jù)的增長,很多SQL語句開始暴露出性能問題,對生產(chǎn)的影響也越來越大,有時可能這些有問題的SQL就是整個系統(tǒng)性能的瓶頸。本文我們就聊聊MYSQL的優(yōu)化
    2021-09-09
  • MySQL敏感數(shù)據(jù)進行加密的幾種方法小結(jié)

    MySQL敏感數(shù)據(jù)進行加密的幾種方法小結(jié)

    本文介紹了在MySQL中對敏感數(shù)據(jù)進行加密的幾種方法,每種方法都有其適用場景和特點,可以根據(jù)具體需求選擇合適的方法來保護數(shù)據(jù)安全,感興趣的可以了解一下
    2024-11-11
  • 數(shù)據(jù)結(jié)構(gòu)-樹(三):多路搜索樹B樹、B+樹

    數(shù)據(jù)結(jié)構(gòu)-樹(三):多路搜索樹B樹、B+樹

    這篇文章主要介紹了多路搜索樹B樹、B+樹,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • MySQL時區(qū)查看及設(shè)置全過程

    MySQL時區(qū)查看及設(shè)置全過程

    在服務(wù)器環(huán)境下,MySQL默認(rèn)時區(qū)可能是UTC,需注意應(yīng)用時區(qū)設(shè)置,若查詢條件使用Now()/sysdate(),會根據(jù)MySQL時區(qū)查詢,導(dǎo)致時間錯亂,可使用`selectnow()`檢查時間準(zhǔn)確性,查看和修改MySQL時區(qū)的方法包括使用命令和修改配置文件
    2025-01-01
  • Mysql模糊查詢優(yōu)化方法及測試詳細講解

    Mysql模糊查詢優(yōu)化方法及測試詳細講解

    這篇文章主要介紹了Mysql模糊查詢優(yōu)化方法及測試,在MySQL中支持模糊匹配的方法有很多,且各有各的優(yōu)點,感興趣想要詳細了解可以參考下文
    2023-05-05
  • MySQL優(yōu)化之如何查找SQL效率低的原因

    MySQL優(yōu)化之如何查找SQL效率低的原因

    這篇文章主要介紹了MySQL優(yōu)化之如何查找SQL效率低的原因 ,需要的朋友可以參考下
    2014-05-05
  • mysql中的保留字段產(chǎn)生的問題

    mysql中的保留字段產(chǎn)生的問題

    我們在使用mysql的時候要注意這方面的問題,一個因為數(shù)據(jù)庫字段命名不當(dāng)造成的問題檢查起來還是相當(dāng)麻煩的,今天遇到這種問題,花費了很長時間才找到問題所在,這是無語
    2015-04-04
  • 詳解windows下mysql的主從同步

    詳解windows下mysql的主從同步

    本文主要對windows下的mysql主從同步進行詳細介紹。具有很好的參考價值,需要的朋友一起來看下吧
    2016-12-12
  • SQL中Limit的基本與高級用法詳解

    SQL中Limit的基本與高級用法詳解

    在SQL中LIMIT是一個用于限制結(jié)果集返回的行數(shù)的子句,這篇文章主要給大家介紹了關(guān)于SQL中Limit的基本與高級用法,文中通過代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用sql具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-04-04

最新評論

乌鲁木齐县| 平罗县| 五华县| 夏津县| 赤水市| 行唐县| 徐汇区| 临清市| 且末县| 平乡县| 集安市| 富裕县| 金湖县| 阿拉善盟| 青阳县| 德清县| 新津县| 禹州市| 思南县| 青阳县| 南投市| 廉江市| 兰西县| 昌都县| 安徽省| 大厂| 宜阳县| 搜索| 隆昌县| 康平县| 贺兰县| 彩票| 闽侯县| 新丰县| 裕民县| 玉田县| 宜丰县| 麟游县| 阳泉市| 娱乐| 本溪市|