最近在使用redis的缓存技术时,在项目中需要在插入mysql数据表记录的同时,缓存数据到redis。在创建数据表时,为了方便,直接使用复制另外一个数据库中的数据表,结果就悲剧了

package com.springboot.chapter7.service.impl;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import com.springboot.chapter7.dao.UserDao;
import com.springboot.chapter7.pojo.User;
import com.springboot.chapter7.service.UserService;/**** imports ****/
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao = null;// 插入用户,最后MyBatis会回填id,取结果id缓存用户@Override@Transactional@CachePut(value = "redisCache", key = "'redis_user_'+#result.id")public User insertUser(User user) {userDao.insertUser(user);return user;}// 获取id,取参数id缓存用户@Override@Transactional@Cacheable(value = "redisCache", key = "'redis_user_'+#id")public User getUser(Long id) {return userDao.getUser(id);}// 更新数据后,充值缓存,使用condition配置项使得结果返回为null,不缓存@Override@Transactional@CachePut(value = "redisCache", condition = "#result != 'null'", key = "'redis_user_'+#id")public User updateUserName(Long id, String userName) {// 此处调用getUser方法,该方法缓存注解失效,// 所以这里还会执行SQL,将查询到数据库最新数据User user = this.getUser(id);if (user == null) {return null;}user.setUserName(userName);userDao.updateUser(user);return user;}// 命中率低,所以不采用缓存机制@Override@Transactionalpublic List<User> findUsers(String userName, String note) {return userDao.findUsers(userName, note);}// 移除缓存@Override@Transactional@CacheEvict(value = "redisCache", key = "'redis_user_'+#id", beforeInvocation = false)public int deleteUser(Long id) {return userDao.deleteUser(id);}
}

就是insertUser方法时,使用的@CachePut将插入到mysql数据库的t_user数据表的数据,同时缓存到redis

建表:t_user(这里复制spring_boot_chapter10数据库的t_user)

spring_boot_chapter10数据库的t_user的建表语句:

drop table if exists user;
create table t_user(id bigint(100) primary key auto_increment,
user_name varchar(20) default null,note varchar(500) default null)
engine=INNODB,default charset=utf8;

建表后的表结构和数据:

现在要创建spring_boot_chapter7数据库的t_user表,由于数据表结构相同,所以直接使用复制语句:

-- 复制spring_boot_chapter10数据库的t_user表,创建spring_boot_chapter7数据库t_user表,会复制数据表结构和数据。
-- 但是复制的表之后,查看建表语句还是有一些差异(有风险)
drop  table if exists t_user;
create table t_user select * from spring_boot_chapter10.t_user;

然后查看复制好的数据表:

发现数据结构和表中数据时一样的

现在来测试insertUser()方法,在插入一条语句后

package com.springboot.chapter7.controller;import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.springboot.chapter7.pojo.User;
import com.springboot.chapter7.service.UserService;/****imports ****/
@Controller
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService = null;@RequestMapping("/getUser")@ResponseBodypublic User getUser(Long id) {return userService.getUser(id);}@RequestMapping("/insertUser")@ResponseBodypublic User insertUser(String userName, String note) {User user = new User();user.setUserName(userName);user.setNote(note);userService.insertUser(user);return user;}@RequestMapping("/findUsers")@ResponseBodypublic List<User> findUsers(String userName, String note) {return userService.findUsers(userName, note);}@RequestMapping("/updateUserName")@ResponseBodypublic Map<String, Object> updateUserName(Long id, String userName) {User user = userService.updateUserName(id, userName);boolean flag = user != null;String message = flag? "更新成功" : "更新失败";return resultMap(flag, message);}@RequestMapping("/deleteUser")@ResponseBodypublic Map<String, Object> deleteUser(Long id) {int result = userService.deleteUser(id);boolean flag = result == 1;String message = flag? "删除成功" : "删除失败";return resultMap(flag, message);}private Map<String, Object> resultMap(boolean success, String message) {Map<String, Object> result = new HashMap<String, Object>();result.put("success", success);result.put("message", message);return result;}
}

使用controller测试insertUser()方法,插入数据:

启动sprigboot项目:

浏览器地址输入:http://localhost:8896/user/insertUser?userName==罗山仔&note=高级java工程师

浏览器响应的json数据,返回一个user对象,但是id的值却是null

现在查看mysql数据库:

查看已经成功插入,但是id=0

现在查看redis数据库,看一下是不是也缓存成功:

发现缓存到redis的键(由redis_user_与id拼接的字符串),发现id也是null

那么为什么会这样的?

问题就是出现在复制语句上,复制语句虽然复制了其他数据表的结构和数据,但是查看chapter7数据库的t_user建表语句会发现差异:

可以看到建表语句与chapter10的t_user建表语句不同,复制了结构和数据,但是并不是完全复制的建表语句

chapter7的t_user建表语句中id没有声明为主键,同时自增也没有了,替代成了default 0,所以每次插入数据,id都是0

所以,需要对chapter7的t_user建表语句做一些修改:

然后运行修改语句,加上主键和自增,然后再进行测试,一切正常:

id已经是4了,查看mysql数据库中插入的数据:

而且之前插入的罗山仔的id也有0变成了2

再查看redis

重新缓存了redis_user_4(redis的键),之前的那个键redis_user_null应该是缓存过期了,刷新之后没了,只剩下redis_user_4

ok,就总结到这里,所以复制表时,虽然方便,,但是也要留意一些坑及风险。所以上边用到的直接复制表结构和数据的语句是有风险的,因此如果要直接从其他数据库复制数据表,下边这样使用是安全的(不会没了主键及自增或者没了索引):

-- 使用其他的复制数据表的语句(复制数据表结构),这种复制语句是安全的,建表语句与spring_boot_chapter10.t_user
-- 的一致
create table t_user like spring_boot_chapter10.t_user;-- 复制表数据
insert into t_user select * FROM spring_boot_chapter10.t_user;

注意:Oracle使用复制语句:

create table t_user  as  select * FROM spring_boot_chapter10.t_user;

也会出现同样的问题,只复制了数据结构和数据,主键和索引等信息不回复制。

mysql数据库复制数据表时的风险相关推荐

  1. MySQL数据库、数据表和字段字符集查询、修改和配置

    一.设置编码 LINUX  修改vi/etc/my.cnf WINDOWS my.ini 在[client]下添加    default-character-set=utf8 在[mysqld]下添加 ...

  2. php如何在mysql数据库里创建表_php创建mysql数据库以及数据表

    php创建mysql数据库以及数据表 用php链接到mysqli,成功后利用,mysqli_query()创建数据库以及数据表. $con = mysqli_connect("localho ...

  3. MySQL数据库与数据表的创建

    MySQL数据库与数据表的创建 文章目录 MySQL数据库与数据表的创建 前言 一.创建数据库 二.使用数据库 三.创建数据表 前言 MySQL的介绍 什么叫数据库: 作用:存储数据,能够长期保存(断 ...

  4. 从零开始学 MySQL —数据库和数据表操作

    ​前言 今天我们学习下核心的内容,学习并实践如何对数据库表和表中的内容做修改,删除,重命名等操作.(想看看周末还有多少爱学习的小伙伴,你们在哪里呀,O(∩_∩)O哈哈~) 1.目录 数据库操作:删除数 ...

  5. 右键计算机管理显示目录名称无效,win10系统打开数据库的数据表时显示“目录名称无效”的恢复方案...

    有关win10系统打开数据库的数据表时显示"目录名称无效"的操作方法想必大家有所耳闻.但是能够对win10系统打开数据库的数据表时显示"目录名称无效"进行实际操 ...

  6. 6.MySQL数据库与数据表操作

    数据库的操作:数据库创建 :数据库删除 数据表的操作:数据表的创建:数据表的修改 (表结构) :数据表的删除 数据库的操作 1.数据库的创建 # 链接mysql数据库后,进入mysql后可以操作数据 ...

  7. Mysql数据库和数据表的创建和信息更改的常用指令

    文章目录 数据库和数据表的创建和信息更改 后续小实验做准备 一. 关于数据库和数据表的其它操作 1)数据库 ①创建数据库 ②显示目前所有的数据库 ③数据库重命名 2.1 先创建新库: 2.2 使用`R ...

  8. oracle跨数据库复制数据表-dblink

    -一.最近有一个这样的需求,之前的数据库(部署在4.9),进程不足,需要迁移 到新的数据库(2.77),包括表结构和表数据,一个一个复制着实比较麻烦,在网上百度了下,才知道有dblink这种实现方式, ...

  9. MySQL数据库及数据表的修改

    1.1修改数据库 修改数据库(mydatabase)默认字符集和校对规则,修改结果如下图所示: 1.2删除数据库 drop database mydatabase; 2.1修改表 (1)修改表结构 例 ...

最新文章

  1. Nginx日志格式设置
  2. python web框架介绍对比
  3. python中文软件-Python
  4. Python 标准库 —— zipfile(读取 zip 文件)
  5. wpf 用户自定义事件传参
  6. SAP中添加自定义菜单
  7. 四、“一场跨越时空持续数世纪的对话”
  8. html div剩下高度设置,使div填充剩余屏幕空间的高度
  9. go:系统参数or函数--未完
  10. 16、java中的集合(3)
  11. iis运行原理 Asp.Net详解IIS内部运行原理
  12. 谷歌承诺未来三年将支付10亿美元新闻费用
  13. linux中哪一个标记可以作为子进程,linux系统编程试卷(答案)
  14. ARC 环境下 dealloc 的使用误区
  15. ZooKeeper 会话的秘密
  16. TOGAF 9 Certification 有用书签
  17. unity开宝箱动画_Unity动画库插件iTween介绍
  18. 完全用 GNU/Linux 工作(原版)
  19. 无法关闭计算机xp,WindowsXP电脑无法关机的解决方法
  20. 【2020年高被引学者】 梅宏 北京大学

热门文章

  1. 如何使用JavaScript获取客户端的IP地址?
  2. 让现有的Git分支跟踪一个远程分支?
  3. 计算机在生活中应用视频,计算机在腐蚀防护中的应用教学视频
  4. java 冗余,java代码冗余
  5. pythonsocket自动化教程_Python基本socket通信控制操作示例
  6. 从无到有axure原型设计_Axure|微信原型制作
  7. CSS3过渡练习-进度条(CSS3)
  8. 天梯—打印沙漏以及剩余个数(C语言)
  9. three.js几何体的旋转,缩放,平移
  10. 漫游飞行_除了防打扰,手机飞行模式还有这些作用