MySQL数据库操作相关问题记录

目录

1.MySQL体系结构与存储引擎

2.数据库兼容性问题以及设置访问权限

3.serverTimezone useSSL 时差8小时

4.同时配置MySQL5和MySQL8在同一主机

5.浅析Sql注入

6.工作中SQL语句整理


 

1.MySQL体系结构与存储引擎

 

MySQL插件式存储引擎,只要写好相应接口,任何引擎都可以访问MySQL,这也是 MySQL 流行的原因之一。
Mysq数据库的体系结构如下:

MySQL 5.7 新特性:

  • 将 Undo 从共享表空间 ibdata 文件中分离出来,安装可自定义文件大小和数量。
  • 增加 temporary 临时表空间,里面存储着临时表或临时查询结果集的数据。
  • ***Buffer Pool 大小可以动态修改,无需重启数据库实例。

MySQL 8.0 新特性

  • 将 InnoDB 表的数据字典和 Undo 都从共享表空间 ibdata 中彻底分离出来。
  • temporary 临时表空间也配置多个nnoDB 存储引擎并能创建索引的物理文件,优化速度。
  • 用户可像 Oracle 一样设置一些表空间给多个表使用,但一个表只能存储在一个表空间中。

存储引擎方面,在5.6版本后默认由 MyISAM变为 InnoDB。InnoDb支持事务和外键、性能也相对较高。

MySQL事务与锁机制

  • 原子性:事务的所有操作,要么全部完成,要么全部不完成,不会结束在某个中间环节。
  • 一致性:事务开始之前和事务结束之后,数据库的完整性限制未被破坏。
  • 隔离性:当多个事务并发访问数据库中的同一数据时,所表现出来的相互关系。使用锁。
  • 持久性:事务完成之后,事务所做的修改进行持久化保存,不会丢失。

并发事务控制

单版本控制-锁:用独占的方式来保证在只有一个版本的情况下事务之间相互隔离,所以锁可以理解为单版本控制。

        在 MySQL 事务中,锁的实现与隔离级别有关系,在 RR(Repeatable Read)隔离级别下,MySQL 为了解决幻读的问题,以牺牲并行度为代价,通过 Gap 锁来防止数据的写入,而这种锁,因为其并行度不够,冲突很多,经常会引起死锁。现在流行的 Row 模式可以避免很多冲突甚至死锁问题,所以推荐默认使用 Row + RC(Read Committed)模式的隔离级别,可以很大程度上提高数据库的读写并行度。

多版本控制-MVCC:为了实现高并发访问,进行多版本处理,并通过事务的可见性来保证合适版本展示。

       每一次对数据库操作,都会在 Undo 日志中记录当前修改记录的事务号及修改前数据状态的存储地址(即 ROLL_PTR),以便回滚。例如,一个读事务查询到当前记录,而最新的事务还未提交,根据原子性,读事务看不到最新数据,但可以去回滚段中找到老版本的数据,这样就生成了多个版本。MVCC巧妙地将稀缺资源的独占互斥转换为并发,优化数据库吞吐量及读写性能。

在 MVCC 并发控制中,读操作可以分为两类: 快照读(Snapshot Read)与当前读 (Current Read)。

快照读:读取的是记录的可见版本(有可能是历史版本),简单的 select 操作,不用加锁。

当前读:读取的是记录的最新版本,并且当前读返回的记录,插入/更新/删除操作,都会加锁。 

注意:MVCC 只在 Read Commited 和 Repeatable Read 两种隔离级别下工作。

2.数据库兼容性问题以及设置访问权限

       大概是每个版本会有些兼容性问题。一方升级了高版本可能是为了得瑟,变厉害了以后呢就不能和以前的老版本朋友一起玩耍了^_^。二是版本升级肯定会有功能的变化,会产生兼容性问题,貌似这才是重点。

登录mysql并使用
use mysql;

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
命令为mysql添加远程连接权限/账号
使用 flush privileges; 命令刷新权限

  1. mysql8版本:com.mysql.cj.jdbc.Driver,MySQL5版本:com.mysql.jdbc.Driver

  2. jdbc:mysql:///你的数据库?useSSL=false&serverTimezone=UTC不要忘了设置时区啥的,8.x版增加了几个参数。

  3.  SSH中,<hibernate.dialect>org.hibernate.dialect.MySQL8Dialect</property>方言MySQL8或5Dialect,关系不大。

3.serverTimezone useSSL 时差8小时

驱动包用的是mysql-connector-java-8.0.11.jar
新版的驱动类改成了com.mysql.cj.jdbc.Driver
新版驱动连接url也有所改动
I、指定时区

//北京时间东八区
serverTimezone=GMT%2B8 

这个时区要设置好,不然会出现时差,
如果你设置serverTimezone=UTC,连接不报错,
但是我们在用java代码插入到数据库时间的时候却出现了问题。
比如在java代码里面插入的时间为:2018-06-24 17:29:56
但是在数据库里面显示的时间却为:2018-06-24 09:29:56
有了8个小时的时差
UTC代表的是全球标准时间 ,但是我们使用的时间是北京时区也就是东八区,领先UTC八个小时。

//北京时间东八区
serverTimezone=GMT%2B8 
//或者使用上海时间
serverTimezone=Asia/Shanghai

为何没有asia/beijing时区?
II、指定是否用ssl连接,true值还报错了

useSSL=false

完整代码:

Class.forName("com.mysql.cj.jdbc.Driver");

        String url="jdbc:mysql://localhost:3306/mydb3?serverTimezone=GMT%2B8&useSSL=false";
        String user="root";
        String password="123";

        Connection connection = DriverManager.getConnection(url, user, password);

        System.out.println(connection);

1、导包mysql-connector-java-8.0.11.jar
2、加载驱动类:Class.forName("com.mysql.cj.jdbc.Driver");
3、定义url,user,password
4、通过DriverManager.getConnection建立连接Connection connection = DriverManager.getConnection(url, user, password);

4.同时配置MySQL5和MySQL8在同一主机

1.官网下载不同版本的mysql包(5.7和8.0)下载后解压到相关文件夹,如图:
2,环境变量问题 可以都配置也可以不配置,不配的话就得到不同mysql的bin下执行mysql -u -p 等命令;在此不进行配置;
3,两个安装目录下配置各自的my.ini文件,注意:两个mysql端口要不一样最好我这里一个3306 一个3307.还有目录不同。其他都是相同的 ,就贴一个吧。

[mysqld]
# 设置3307端口 
port=3307
# 设置mysql的安装目录
basedir=你的mysql安装目录   # 切记此处一定要用双斜杠\\,单斜杠也行。
# 设置mysql数据库的数据的存放目录
datadir=安装目录\\Data   # 此处同上
# 允许最大连接数
max_connections=200
# 允许连接失败的次数。这是为了防止有人从该主机试图攻击数据库系统
max_connect_errors=10
# 服务端使用的字符集默认为UTF8
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 默认使用“mysql_native_password”插件认证
default_authentication_plugin=mysql_native_password
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[client]
# 设置mysql客户端连接服务端时默认使用的端口
port=3307
default-character-set=utf8

4,在各自的bin目录下进行数据库安装和服务注册

     mysqld --initialize --console:此时记住临时密码root@localhost:后面的“随机数”就是初始密码(不含首位空格)。
     mysqld --install MYSQL5 或者mysqld --install MYSQL8 分别起两个服务名字

5,注册表服务指向确认,确认两个服务 不同的执行路径。

5,最后可以set password for username@localhost=password('新密码')

5,浅析Sql注入

有一张学生表


现在需要根据学生名称获取学生的期末考试分数。

1.public static void getStudent(String name) throws ClassNotFoundException {
2.    Connection conn = null;
3.    Statement stmt = null;
4.    ResultSet rs = null;
5.    try {
6.      Class.forName(JDBC_DRIVER);
7.      conn = DriverManager.getConnection(DB_URL, USER, PASS);
8.      stmt = conn.createStatement();
9.      rs = stmt.executeQuery("select name,score from student where name =' " + name +"'");
10.      while (rs.next()) {
11.        System.out.println(rs.getString("name") + ":" + rs.getInt("score"));
12.      }
13.    } catch (SQLException e) {
14.      // ignore
15.    } finally {
16.      if (rs != null) {
17.        try {
18.          rs.close();
19.        } catch (Exception e) {
20.          // ignore
21.        }
22.      }
23.      if (stmt != null) {
24.        try {
25.          stmt.close();
26.        } catch (Exception e) {
27.          // ignore
28.        }
29.      }
30.      if (conn != null) {
31.        try {
32.          conn.close();
33.        } catch (SQLException e) {
34.          // ignore
35.        }
36.      }
37.    }
38.  }

1. 请指出上面这段程序存在什么安全风险?

用户在输入表单,通过恶意sql欺骗服务器。根源在于动态拼接sql;

此时可以使用preparedstatement。?占位符代表参数就可以简单防止sql注入了。

在一个就是注意封装数据库报错信息。还有就是涉密信息一定加密处理。

6,工作中SQL语句整理

在这里插入图片描述
窗口:记录集合
窗口函数:在满足某些条件的记录集合上执行的特殊函数,对于每条记录都要在此窗口内执行函数。有的函数随着记录的不同,窗口大小都是固定的,称为静态窗口;有的函数则相反,不同的记录对应着不同的窗口,称为滑动窗口

1. 窗口函数和普通聚合函数的区别:
①聚合函数是将多条记录聚合为一条;窗口函数是每条记录都会执行,有几条记录执行完还是几条。
②聚合函数也可以用于窗口函数。

2. 窗口函数的基本用法:
函数名 OVER 子句

over关键字用来指定函数执行的窗口范围,若后面括号中什么都不写,则意味着窗口包含满足WHERE条件的所有行,窗口函数基于所有行进行计算;如果不为空,则支持以下4中语法来设置窗口。
①window_name:给窗口指定一个别名。如果SQL中涉及的窗口较多,采用别名可以看起来更清晰易读;
②PARTITION BY 子句:窗口按照哪些字段进行分组,窗口函数在不同的分组上分别执行;
③ORDER BY子句:按照哪些字段进行排序,窗口函数将按照排序后的记录顺序进行编号;
④FRAME子句:FRAME是当前分区的一个子集,子句用来定义子集的规则,通常用来作为滑动窗口使用。

ROW_NUMBER():顺序排序——1、2、3
RANK():并列排序,跳过重复序号——1、1、3
DENSE_RANK():并列排序,不跳过重复序号——1、1、2

--------------------------------------------------------------------------------------------------------------------------------------------------------------

-- 查询昨日一整天的数据
SELECT * from 表名where date(列名) in (DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 DAY) ,'%Y-%m-%d 00:00:00') ,DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 DAY) ,'%Y-%m-%d 23:59:59') )

-- 查询今日开始到当前时间的数据
SELECT DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 0 DAY) ,'%Y-%m-%d 00:00:00') AS '今日开始时间' ,DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 0 DAY) ,'%Y-%m-%d %H:%i:%s') AS '今日当前时间'

-- 查询上一周的数据
select * from 表名WHERE YEARWEEK( date_format(alarm_time, '%Y-%m-%d')) = YEARWEEK(now()) - 1

-- 查询从现在开始一周内数据

@Select("select count(*) from 表名where DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(列名)") 
从现在开始前7天的数据不算小时 就算天数 Now就是自带小时格式了

select * from 表名 where DATE_SUB(now(), INTERVAL 7 DAY) <= date(列名)
或者 规范格式化:
select * from 表名 where DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 7 DAY),'%Y-%m-%d %H:%M:%S')<=date(列名)

-- 查询上月一整个月的数据
SELECT DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 MONTH) ,'%Y-%m-01 00:00:00') AS '上个月开始时间' ,
date_sub(date_sub(date_format(now(),'%Y-%m-%d 23:59:59'),interval extract( day from now()) day),interval 0 month) AS '上个月结束时间' 
-- 查询本月开始到当前时间的数据
SELECT DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 0 MONTH) ,'%Y-%m-01 00:00:00') AS '本月开始时间' ,DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 0 DAY) ,'%Y-%m-%d %H:%i:%s') AS '本月当前时间'  

-- 查询去年一整年的数据
SELECT DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 YEAR) ,'%Y-01-01 00:00:00') AS '去年开始时间' ,
DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 YEAR) ,'%Y-12-31 23:59:59') AS '去年结束时间' 
-- 查询本年开始到当前时间的数据
SELECT DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 0 DAY) ,'%Y-01-01 00:00:00') AS '本年开始时间' ,DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 0 DAY) ,'%Y-%m-%d %H:%i:%s') AS '本年当前时间'

--查询12月30当天数据
 SELECT * from 表名 where date(列名) in (('2019-12-30 00:00:00') ,('2019-12-30 23:59:59'))

-- SELECT NOW(),CURDATE(),CURTIME()  注意格式是不一样的

网络转载:https://www.cnblogs.com/caidao-cbj/p/4582758.html

今天  select * from 表名 where to_days(时间字段名) = to_days(now());

昨天  SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 时间字段名) <= 1

7天    SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(时间字段名)

近30天  SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(时间字段名)

本月   SELECT * FROM 表名 WHERE DATE_FORMAT( 时间字段名, '%Y%m' ) = DATE_FORMAT( CURDATE( ) , '%Y%m' )

上月 SELECT * FROM 表名 WHERE PERIOD_DIFF( date_format( now( ) , '%Y%m' ) , date_format( 时间字段名, '%Y%m' ) ) =1

#查询本季度数据
select * from `ht_invoice_information` where QUARTER(create_date)=QUARTER(now());
#查询上季度数据
select * from `ht_invoice_information` where QUARTER(create_date)=QUARTER(DATE_SUB(now(),interval 1 QUARTER));
#查询本年数据
select * from `ht_invoice_information` where YEAR(create_date)=YEAR(NOW());
#查询上年数据
select * from `ht_invoice_information` where year(create_date)=year(date_sub(now(),interval 1 year));

查询当前这周的数据 
SELECT name,submittime FROM enterprise WHERE YEARWEEK(date_format(submittime,'%Y-%m-%d')) = YEARWEEK(now());

查询上周的数据
SELECT name,submittime FROM enterprise WHERE YEARWEEK(date_format(submittime,'%Y-%m-%d')) = YEARWEEK(now())-1;

查询当前月份的数据
select name,submittime from enterprise   where date_format(submittime,'%Y-%m')=date_format(now(),'%Y-%m')

查询距离当前现在6个月的数据
select name,submittime from enterprise where submittime between date_sub(now(),interval 6 month) and now();

查询上个月的数据
select name,submittime from enterprise   where date_format(submittime,'%Y-%m')=date_format(DATE_SUB(curdate(), INTERVAL 1 MONTH),'%Y-%m')

select * from ` user ` where DATE_FORMAT(pudate, ' %Y%m ' ) = DATE_FORMAT(CURDATE(), ' %Y%m ' ) ;

select * from user where WEEKOFYEAR(FROM_UNIXTIME(pudate,'%y-%m-%d')) = WEEKOFYEAR(now())

select * from user where MONTH (FROM_UNIXTIME(pudate, ' %y-%m-%d ' )) = MONTH (now())

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.Thompson

相互学习,欢迎指正。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值