mysql行級鎖 java 實現

mysql行級鎖:

  1. 數據庫引擎: InnerDB,其他的不支持行鎖
  2. 所在方法要加上事務註解, 必須加上: @Transactional(isolation = Isolation.READ_COMMITTED)
  3. 查詢sql舉例:

    select * from global_lock where object=#{object} for update;

    注意:
  4. timeout必須設置,否則,一旦行鎖被鎖定,另一個調用的方法將永久的阻塞。加了超時後,如果行鎖被獲取,則超時提示
  5. 數據表必須加索引,否則,將採用表級鎖
  6. 行鎖可以重複調,只要不是同一行,可以跨表

例子如下:
數據庫

CREATE TABLE `global_lock` (
  `object` varchar(20) DEFAULT NULL,
  **UNIQUE KEY `idx_global_lock_object` (`object`)**
) ENGINE=InnoDB DEFAULT CHARSET=utf8

在這裏插入圖片描述
項目
在這裏插入圖片描述
GlobalLockController .java

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sm.rowlock.mapper.GlobalLockMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class GlobalLockController {
    private static Logger logger = LoggerFactory.getLogger(GlobalLockController.class);
    
    @Autowired
    private GlobalLockMapper globalLockMapper;
    
    @RequestMapping("/getLock")
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void getLock() {
        globalLockMapper.getLock("object");
        System.out.println("111");
    }
    
    @RequestMapping("/getLock2")
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void getLock2() {
        try {
            globalLockMapper.getLock("object");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("111");
    }
}

GlobalLockEntity .java

public class GlobalLockEntity {
    private String object;

    public String getObject() {
        return object;
    }

    public void setObject(String object) {
        this.object = object;
    }
}

GlobalLockMapper .java

import org.apache.ibatis.annotations.Param;

public interface GlobalLockMapper {
    void getLock(@Param("object")String object);
}

MainApp.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@tk.mybatis.spring.annotation.MapperScan(basePackages="org.sm.rowlock.mapper")
public class MainApp {

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

GlobalLockMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="org.sm.rowlock.mapper.GlobalLockMapper">
    <resultMap id="BaseResultMap" type="org.sm.rowlock.entity.GlobalLockEntity">
        <result column="object" property="object" jdbcType="VARCHAR"/>
    </resultMap>
    
    <select id="getLock" resultMap="BaseResultMap" timeout="2">
        select * from global_lock where object=#{object} for update;
    </select>
</mapper>

application.properties



server.port=8081

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://ip:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=user
spring.datasource.password=password


mybatis.type-aliases-package=org.sm.rowlock.entity
mybatis.mapper-locations=classpath:mappers/*.xml
mybatis.configuration.map-underscore-to-camel-case=true

mapper.mappers=tk.mybatis.mapper.common.Mapper
mapper.not-empty=false
mapper.identity=MYSQL
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章