Redis事务与MySQL事务的区别
1.想着 在springboot事务中,第一步insert mysql 第二步 更新到redis中
@Transactional(rollbackFor={Exception.class}) public void addChannel(MesChannelVo mesChannelVo) { //id String id = GenerateCodeUtil.generateUUID(); //当前时间 String nowDateTime = DateUtil.DateToString(new Date(), DateStyle.YYYY_MM_DD_HH_MM_SS); MesChannel mesChannel = new MesChannel(); Beans.copy().from(mesChannelVo).to(mesChannel); mesChannel.setId(id); mesChannel.setValidStatus("Y"); mesChannel.setCreateTime(nowDateTime); mesChannel.setUpdateTime(nowDateTime); //1.插入数据库中 mesChannelDao.insert(mesChannel); // 2.更新缓存中 List<MesChannel> mesChannelsRedis = new ArrayList<>(); List<MesChannel> mesChannels = mesChannelDao.selectByEntry(mesChannel); if(mesChannels != null && !mesChannels.isEmpty()){ for (MesChannel mesCh : mesChannels){ mesChannelsRedis.clear(); mesChannelsRedis.add(mesCh); String channelType_mesTypeCode = mesCh.getChannelType() + "_" + mesCh.getMesTypeCode(); jedisUtil.setJson(channelType_mesTypeCode, JSON.toJSONString(mesChannelsRedis)); } } //3.测试事务回滚 int[] i = null; int i1 = i[0]; }
1.1 现象 mysql 数据库回滚 redis 正常插入
2 redis 事务
2.1redis命令是原子性的,事务不是原子性的
- 若事务队列中存在命令错误(类似java编译性错误),执行
exec
,所有命令都不会执行 - 若事务中存在语法错误(类似java 1/0的运行时异常),执行
exec
,正确命令会被执行,错误命令抛出异常
3.如果开启事务,操作不会被立即执行,将会返回null值
3.0 mysql 和 redis 事务
3.2. 脏读:事务A读取了B更新的数据,然后B回滚事务A读取到的就是脏数据
--A事务 读取 B事务期间修改的数据 造成的脏读
不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致前后结果不一致。
-- A事务 读取 数据,B事务对数据进行修改 ,事务前后的数据 产生的不可重复读
幻读:A管理员将学生按照分数分为ABCDE,B管理员在A操作完全部数据之后发现有一条记录没操作,好像出现幻觉一样。
3.3 mysql 的默认隔离级别 可重复读 A事务开启后 读取的数据 不会读到B事务提交的修改
3.4 mysql 开启事务
4. 插入->查询操作 在一个事务中,事务具有数据一致性,所以查询可以读到新插入的数据
启动类中添加 @EnableTransactionManagement
@Transactional 该注解 mybatis 开启了一级缓存
@Override @Transactional(rollbackFor={Exception.class}) public void addChannel(MesChannelVo mesChannelVo) { //id String id = GenerateCodeUtil.generateUUID(); //当前时间 String nowDateTime = DateUtil.DateToString(new Date(), DateStyle.YYYY_MM_DD_HH_MM_SS); MesChannel mesChannel = new MesChannel(); Beans.copy().from(mesChannelVo).to(mesChannel); mesChannel.setId(id); mesChannel.setValidStatus("Y"); mesChannel.setCreateTime(nowDateTime); mesChannel.setUpdateTime(nowDateTime); //1.插入数据库中 int insert = mesChannelDao.insert(mesChannel); if(insert > 0){ // 2.更新缓存中 List<MesChannel> mesChannelsRedis = new ArrayList<>(); List<MesChannel> mesChannels = mesChannelDao.selectByEntry(mesChannel); if(mesChannels != null && !mesChannels.isEmpty()){ for (MesChannel mesCh : mesChannels){ mesChannelsRedis.clear(); mesChannelsRedis.add(mesCh); String channelType_mesTypeCode = mesCh.getChannelType() + "_" + mesCh.getMesTypeCode(); jedisUtil.setJson(channelType_mesTypeCode, JSON.toJSONString(mesChannelsRedis)); } } } }
4.1 console 控制台打印
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f23981c]
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@69b783ea] will be managed by Spring
==> Preparing: insert into mes_channel (id, channel_name, channel_type, mes_type_code, mes_company_code, channel_key, valid_status, create_time, update_time, flag ) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
==> Parameters: 50ABC62CAECC4FB79211893A43FCA4FE(String), gaga(String), gaga(String), marketType(String), dahantricom(String), gaga(String), Y(String), 2022-03-28 13:58:35(String), 2022-03-28 13:58:35(String), null
<== Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f23981c]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f23981c] from current transaction
==> Preparing: select id, channel_name, channel_type, mes_type_code, mes_company_code, channel_key, valid_status, create_time, update_time, flag from mes_channel WHERE id = ? and channel_name = ? and channel_type = ? and mes_type_code = ? and mes_company_code = ? and channel_key = ? and valid_status = ? and create_time = ? and update_time = ?
==> Parameters: 50ABC62CAECC4FB79211893A43FCA4FE(String), gaga(String), gaga(String), marketType(String), dahantricom(String), gaga(String), Y(String), 2022-03-28 13:58:35(String), 2022-03-28 13:58:35(String)
<== Columns: id, channel_name, channel_type, mes_type_code, mes_company_code, channel_key, valid_status, create_time, update_time, flag
<== Row: 50ABC62CAECC4FB79211893A43FCA4FE, gaga, gaga, marketType, dahantricom, gaga, Y, 2022-03-28 13:58:35, 2022-03-28 13:58:35, null
<== Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f23981c]
--最后提交事务
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f23981c]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f23981c]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f23981c]
4.2 事务没有提交 所有mysql 中查询不到新增的数据
4.3 navicat 中 开启另外一个事务 测试 mysql 的隔离级别 可重复读
A 事务 开启后 执行select ,数据库中的数据是没有变化 ;然后 执行完新增channel的功能,执行查询sql 数据同样没有改变
但是 此时 重新开一个事务查询 --- 不使用Begin mysql 默认每执行一条sql 开启一个事务自动提交
查询到了新增的数据
mysql 的可重复读隔离级别; A事务开启期间 读取不到另外一个事务修改的数据
5. 插入->查询操作 不在一个事务中 注释事务注解
每个操作是一个事务,在执行查询的时候,插入操作已经提交,执行完这条语句的时候 事务已经提交 ,数据库已经存在数据
--插入事务
Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@56adcb0a] was not registered for synchronization because synchronization is not active JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@cf0c273] will not be managed by Spring ==> Preparing: insert into mes_channel (id, channel_name, channel_type, mes_type_code, mes_company_code, channel_key, valid_status, create_time, update_time, flag ) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) ==> Parameters: D9C7E6687D66455CA1F5322AB8D47C60(String), gag(String), agga(String), marketType(String), dahantricom(String), gag(String), Y(String), 2022-03-28 11:36:09(String), 2022-03-28 11:36:09(String), null <== Updates: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@56adcb0a]
--查询事务 Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@55933825] was not registered for synchronization because synchronization is not active JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@cf0c273] will not be managed by Spring ==> Preparing: select id, channel_name, channel_type, mes_type_code, mes_company_code, channel_key, valid_status, create_time, update_time, flag from mes_channel WHERE id = ? and channel_name = ? and channel_type = ? and mes_type_code = ? and mes_company_code = ? and channel_key = ? and valid_status = ? and create_time = ? and update_time = ? ==> Parameters: D9C7E6687D66455CA1F5322AB8D47C60(String), gag(String), agga(String), marketType(String), dahantricom(String), gag(String), Y(String), 2022-03-28 11:36:09(String), 2022-03-28 11:36:09(String) <== Columns: id, channel_name, channel_type, mes_type_code, mes_company_code, channel_key, valid_status, create_time, update_time, flag <== Row: D9C7E6687D66455CA1F5322AB8D47C60, gag, agga, marketType, dahantricom, gag, Y, 2022-03-28 11:36:09, 2022-03-28 11:36:09, null <== Total: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@55933825]
5.1 Closing non transactional SqlSession
关闭非事务性 SqlSession
5.2 Creating a new SqlSession
5.3 SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@258ab2ab] was not registered for synchronization because synchronization is not active
数据库连接连接相关信息
5.4 JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3b6eb5ed] will not be managed by Spring
jdbc连接不是spring管理的
springboot + mybatis出现was not registered for synchronization because synchronization is not active