select for update 即排他锁,排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
作用:保证数据的一致性,为了在查询时,避免其他用户对该表进行插入,修改或删除等操作,造成表数据的不一致性。
(资料图片仅供参考)
这里只讲述和排他锁有关内容。
INFORMATION_SCHEMA 是mysql自带的元数据数据库INNODB_TRX是MYSQL中事务和锁相关的表INNODB_TRX表提供了当前INNODB引擎内每个事务的信息(除只读事务外),包括当一个事务启动,事务是否在等待一个锁,以及正在执行的SQL语句。
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
这里使用mysql数据库为例。
-- ---------------------------- -- 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");
├─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
引入mysql driver、lombok、mybatis-plus等依赖
4.0.0 org.springframework.boot spring-boot-starter-parent 2.6.5 com.xy spring-boot 0.0.1-SNAPSHOT spring-boot Demo project for Spring Boot 11 com.baomidou mybatis-plus-boot-starter 3.5.1 org.springframework.boot spring-boot-devtools runtime true mysql mysql-connector-java runtime org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok
Mapper映射xml文件内容如下:ConfigMapper.xml
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 getLockedConfig(@Param("name") String name, @Param("value") String value); }
ConfigDao.java 接口类及其实现类
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{ /** * 通过名称和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 ServiceImplimplements 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; }
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); } }
ExclusiveLocksRunner 该类实现了ApplicationRunner接口,其含义是在SpringBoot工程启动之后,执行的操作。该类必须注入到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); } }
疑问:
ExclusiveLocksRunner类中run方法上的@Transactional 注解是否起作用?select…for update 是否有效?select…for update 加锁之后,未释放之前,再次加锁时,返回的lockedConfig内容是什么?
断点位置:
事务拦截器(使用AOP的方式对@Transactional注解进行处理)inovke方法处断点: org.springframework.transaction.interceptor.TransactionInterceptor#invokeExclusiveLocksRunner.java run 方法Debug如图所示,证明ExclusiveLocksRunner.java中run 方法上@Transcational 注解是有效的。
进入invokeWithinTransaction 调用事务方法继续调试,
整个调用流程如下:创建事务——> 调用run方法 -> commit提交事务。
进入run方法:根据检索条件查询内容,并对其内容设置类排他锁。
LOG信息如下:
查询mysql中是否存在对应的排他锁信息
-- 执行如下信息,查看是否存在Lock信息 SELECT trx_id, trx_state, trx_started, trx_rows_locked FROM INFORMATION_SCHEMA.INNODB_TRX;
结果如下:
证明:数据库中已经存在排他锁信息,证明该加锁方式是OK的,并在大概在第2行。
在数据库中,再次执行以下SQL,进行查询,得到结果为null。证书排他锁未释放之前,再次枷锁时,返回内容为null,因此select…for update 加锁之后,未释放之前,再次加锁时,返回的lockedConfig内容时null。
到此这篇关于SELECT… FOR UPDATE 排他锁的实现的文章就介绍到这了,更多相关SELECT… FOR UPDATE 排他锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
中新网北京5月19日电(记者 陈杭)北京市疾病预防控制中心副主任刘晓峰在19日召开的北京新冠肺炎疫情防控工作新闻发布会上表示,4月22日
中新网北京5月19日电(记者 陈杭)北京市疾病预防控制中心副主任刘晓峰在19日召开的北京新冠肺炎疫情防控工作新闻发布会上表示,当前社
中新网北京5月19日电(记者 陈杭)北京市疾病预防控制中心副主任刘晓峰在19日召开的北京新冠肺炎疫情防控工作新闻发布会上表示,截至202
中新网长沙5月19日电 (记者 傅煜)今年以来,湖南共拦截诈骗电话375 1万次,封堵涉诈有害域名100 4万个,冻结涉案资金14 3亿元,劝阻2
中新网绍兴5月19日电(记者 项菁)“绍兴全市共设置河长4130名、湖长916名,实现每一个水体都有人管护。同时,累计建成‘美丽河湖’68条