mysql8.0

Mysql8.0 新特性介绍

一 性能升级

官方表示MySQL 8.0 的速度要比 MySQL 5.7 快 2 倍。MySQL 8.0 在读/写工作负载、IO 密集型工作负载、以及高竞争工作负载时相比MySQL5.7有更好的性能。

可以使用一款mysql压测工具sysbench,是一款非常方便的工具,它可以帮你在数据库中构建大量的大数据,自动的创建表,接着模拟很多的线程去并发访问你的数据库,可以执行各种各样用于读写数据库的sql语句,以及提交复杂的事物

二 NoSql文档支持

MySQL 从 5.7 版本开始提供 NoSQL 存储功能,目前在 8.0 版本中这部分功能也得到了更大的改进。该项功能消除了对独立的 NoSQL 文档数据库的需求,而 MySQL 文档存储也为 schema-less 模式的 JSON 文档提供了多文档事务支持和完整的 ACID 合规性。

要在MySQL中存储数据,就必须定义数据库和表结构(schema),这是一个主要的限制。为了应对这一点,从MySQL 5.7开始,MySQL支恃了 JavaScript对象表示(JavaScriptObject Notation,JSON) 数据类型。在5.7之前,这类数据不是单独的数据类型,会被存储为字符串。新的JSON数据类型提供了自动验证的JSON文档以及优化的存储格式。

JSON文档以二进制格式存储,它提供以下功能:

对文档元素的快速读取访问。
当服务器再次读取JSON文档时,不需要重新解析文本获取该值。
通过键或数组索引直接查找子对象或嵌套值,而不需要读取文档中的所有值

2.1 创建测试表
CREATE TABLE tab_base_info (
id bigint(20) NOT NULL AUTO_INCREMENT,
content json NULL,
PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4

SELECT id,content FROM tab_base_info;

2.2 插入数据
INSERT INTO tab_base_info (id,content) VALUES(1,’{“age”:12,“name”:“小李子”,“sex”:“男”}’);

Mysql 会自动校验json的数据格式
INSERT INTO tab_base_info (id,content) VALUES(2,’{“age”:12,“name”:“小李子”,“sex”:“男”,“phone”:{“iccid”:“8986”,“imsi”:"1234 }}’) (少一个引号)

2.3 查询数据
2.3.1 -> ->>
它两的主要作用就是一个是查询字段值包含引号,一个不包含引号
等价于之前的:

JSON_UNQUOTE(column -> path)

JSON_UNQUOTE(JSON_EXTRACT(column,path))

SELECT id , content -> ‘$.sex’ sex FROM tab_base_info;

SELECT id , content ->> ‘$.sex’ sex FROM tab_base_info;

SELECT id,content FROM tab_base_info WHERE content->> ‘$.phone.imsi’ = ‘1234’;

2.3.2 JSON_PRETTY
格式化json字符串

INSERT INTO tab_base_info (id,content) VALUES (3,’{“location”:“IN”,“phone”:"+11800000000",“email”:“abc@example.com”,“address”:{“line1”:“abc”,“line2”:“xyz street”,“city”:“Bangalore”,“pin”:“560103”}}’);

SELECT id, JSON_PRETTY(content) FROM tab_base_info WHERE id = 3;

2.3.3 JSON_CONTAINS
JSON_CONTAINS函数查询数据。如果找到了数据,则返回1,否则返回NULL
SELECT JSON_CONTAINS(content->> ‘$.phone.imsi’,‘1234’) FROM tab_base_info where id = 2;

2.3.4 JSON_CONTAINS_PATH
使用JSON_CONTAINS_PATH函数检查json 字段是否存在,存在返回1,不存在返回0.
SELECT JSON_CONTAINS_PATH(content,‘one’,’$.phone.imsi’) FROM tab_base_info where id = 2;

SELECT JSON_CONTAINS_PATH(content,‘one’,’ . p h o n e . i m s i ′ , ′ .phone.imsi',' .phone.imsi,.phone.iccid’) FROM tab_base_info where id = 2;

SELECT JSON_CONTAINS_PATH(content,‘all’,’ . p h o n e . i m s i ′ , ′ .phone.imsi',' .phone.imsi,.phone.iccid’) FROM tab_base_info where id = 2;

one 和 all的区别:
one表示至少应该存在一个键,检查phone.imsi或者phone.iccid是否存在
如果要检查phone.imsi或者phone.iccid是否同时存在,可以使用all,而不是one

2.4 更新数据
 可以使用三种不同的函数来修改数据:JSON_SET()、JSON_INSERT()和JSON _REPLACE()。 在MySQL 8之前的版本中,我们还需要对整个列进行完整的更新,这并不是最佳的方法。

2.4.1 JSON_SET()
替换现有值并添加不存在的值

update tab_base_info set content = json_set(content," . n a m e " , " 小 六 子 " , " .name","小六子"," .name","",".phone.smsc",‘2020’) where id = 2;

2.4.2 JSON_INSERT
插入值,但不替换现有值
update tab_base_info set content = json_insert(content," . n a m e " , " 小 李 子 " , " .name","小李子"," .name","",".phone.pin1",‘1234’) where id = 2;

2.4.3 JSON_REPLACE()
替换现有值,但是不会插入新值
update tab_base_info set content = json_replace(content," . n a m e " , " 小 李 子 " , " .name","小李子"," .name","",".phone.puk1",‘1234’) where id = 2;

2.5 删除数据
2.5.1 JSON_REMOVE()
update tab_base_info set content = json_remove(content,"$.age") where id = 2;

2.6 其他函数
2.6.1 JSON_KEYS()
获取JSON文档中所有的属性
SELECT json_keys(content),json_keys(content ->> ‘$.phone’) FROM tab_base_info where id = 2;

2.6.2 JSON_LENGTH()
给出JSON文档中的元素数

SELECT json_length(content),json_length(content ->> ‘$.phone’) FROM tab_base_info where id = 2;

2.6.3 JSON_ARRAYAGG()
将多行数据组合成json数组

创建表结构
CREATE TABLE t1 (
sex varchar(8) DEFAULT NULL,
age int DEFAULT NULL,
phone varchar(8)
)
插入值
INSERT INTO t1(sex, age, phone) VALUES
(“key1”, 12, “v1”),
(“key2”, 13, “v2”),
(“key3”, 14, “v3”);

查询结果

#将查询出的字段聚合成为一个json数组
SELECT JSON_ARRAYAGG(sex) AS keys FROM t1;

分组聚合

SELECT JSON_ARRAYAGG(sex) AS keys FROM t1 GROUP BY age;

插入一条数据

INSERT INTO t1(sex, age, phone) VALUES
(“key4”, 12, “v4”)

查询结果

#分组聚合

2.6.4 JSON_OBJECTAGG
把某两列的值整合为JSON对象

SELECT JSON_OBJECTAGG(sex, age) AS key_val FROM t1;

分组聚合

SELECT JSON_OBJECTAGG(sex, age) AS key_val FROM t1 GROUP BY age;

创建用户表

CREATE TABLE test_user (
id bigint(20) NOT NULL AUTO_INCREMENT,
name varchar(255) DEFAULT NULL,
sex varchar(8) DEFAULT NULL,
age tinyint(4) DEFAULT NULL,
phone varchar(8) DEFAULT NULL,
PRIMARY KEY (id)
)

创建爱好表

CREATE TABLE test_hobby (
id bigint(20) NOT NULL AUTO_INCREMENT,
name varchar(100) DEFAULT NULL,
PRIMARY KEY (id)
)

创建用户爱好关系表

CREATE TABLE test_user_hobby (
id bigint(20) NOT NULL AUTO_INCREMENT,
user_id bigint(20) DEFAULT NULL,
hobby_id bigint(20) DEFAULT NULL,
hobby_value varchar(100) DEFAULT NULL,
PRIMARY KEY (id)
)

插入数据 用户表

INSERT INTO test_user(id, name, sex, age, phone) VALUES (1, ‘小李子’, ‘男’, 20, ‘181’);
INSERT INTO test_user(id, name, sex, age, phone) VALUES (2, ‘小六子’, ‘男’, 21, ‘181’);

插入爱好表

INSERT INTO test_hobby(id, name) VALUES (1, ‘音乐’);
INSERT INTO test_hobby(id, name) VALUES (2, ‘球类’);

#插入用户爱好关系表
INSERT INTO test_user_hobby(id, user_id, hobby_id, hobby_value) VALUES (1, 1, 1, ‘国歌’);
INSERT INTO test_user_hobby(id, user_id, hobby_id, hobby_value) VALUES (2, 1, 2, ‘篮球’);
INSERT INTO test_user_hobby(id, user_id, hobby_id, hobby_value) VALUES (3, 2, 1, ‘国歌2’);
INSERT INTO test_user_hobby(id, user_id, hobby_id, hobby_value) VALUES (4, 2, 2, ‘乒乓球’);

查询聚合json

SELECT
JSON_OBJECT(“id”,tu.id,
“name”,tu.name,
“sex”,tu.sex,
“hobby”,JSON_OBJECTAGG(tb.name,tuh.hobby_value)) as json
FROM test_user_hobby tuh

JOIN test_user tu ON tuh.user_id = tu.id
JOIN test_hobby tb ON tuh.hobby_id = tb.id
GROUP BY tu.id

2.6.5 JSON_TABLE()
将json字符串转换成表结构查询
SELECT * FROM JSON_TABLE (’[{“name”:“小李子”,“age”:12,“phone”:{}}]’
," [ ∗ ] " C O L U M N S ( r o w i d F O R O R D I N A L I T Y , a g e i n t P A T H " [*]" COLUMNS( rowid FOR ORDINALITY, age int PATH " []"COLUMNS(rowidFORORDINALITY,ageintPATH".age",
name varchar(100) PATH “ . n a m e " , p h o n e j s o n P A T H " .name", phone json PATH " .name",phonejsonPATH".phone”)) a

https://dev.mysql.com/doc/refman/8.0/en/json-functions.html

2.7 SpringBoot + mybaits 整合mysql8.0 + json
2.7.1 pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.3</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.23</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>log4j-over-slf4j</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.73</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>

</dependencies>

2.7.2 application.yml

mysql连接配置

spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://10.1.72.44:3306/testdb?useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password: wa12345
driverClassName: com.mysql.cj.jdbc.Driver
minIdle: 5
initialSize: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 3000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,wall,log4j
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

自定义mybaits类型处理器扫描包

mybatis:
type-handlers-package: config.mybaits.handler

2.7.3 MySqlJsonHandler.java 自定义类型处理器
package config.mybaits.handler;

import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.*;

/**

  • @description 用以mysql中json格式的字段,进行转换的自定义转换器,转换为实体类的JSONObject属性
    */
    @MappedTypes(JSONObject.class)
    @MappedJdbcTypes(JdbcType. OTHER)
    public class MySqlJsonHandler extends BaseTypeHandler {

    /**

    • 设置非空参数
    • @param ps
    • @param i
    • @param parameter
    • @param jdbcType
    • @throws SQLException
      */
      @Override
      public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException {
      ps.setString(i, String.valueOf(parameter.toJSONString()));
      }

    /**

    • 根据列名,获取可以为空的结果
    • @param rs
    • @param columnName
    • @return
    • @throws SQLException
      */
      @Override
      public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException {
      String sqlJson = rs.getString(columnName);
      if (null != sqlJson) {
      return JSONObject.parseObject(sqlJson);
      }
      return null;
      }

    /**

    • 根据列索引,获取可以为空的结果
    • @param rs
    • @param columnIndex
    • @return
    • @throws SQLException
      */
      @Override
      public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
      String sqlJson = rs.getString(columnIndex);
      if (null != sqlJson) {
      return JSONObject.parseObject(sqlJson);
      }
      return null;
      }

    @Override
    public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    String sqlJson = cs.getString(columnIndex);
    if (null != sqlJson) {
    return JSONObject.parseObject(sqlJson);
    }
    return null;
    }
    }

2.7.4 定义domain

import com.alibaba.fastjson.JSONObject;
import lombok.Data;

/**

  • @author zhibin.wang
  • @desc
    **/

@Data
public class BaseInfoDO {

private Long id;

/**
* 使用jsonobject 映射字段
*/
private JSONObject content;

}

2.7.5 定义mapper
import config.mybaits.domain.BaseInfoDO;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.JdbcType;

/**

  • @author zhibin.wang

  • @desc
    **/
    @Mapper
    public interface BaseInfoMapper {

    /**

    • 保存数据库信息
    • @param baseInfoDO
    • @return
      */
      @Insert(“INSERT INTO tab_base_info (content) VALUES(#{content,jdbcType=OTHER,typeHandler=config.mybaits.handler.MySqlJsonHandler})”)
      @Options(keyColumn = “id”,keyProperty = “id”,useGeneratedKeys = true)
      int save(BaseInfoDO baseInfoDO);

    /**

    • 根据id查询数据
    • @param id
    • @return
      */
      @Select(“SELECT id,content FROM tab_base_info where id = #{id}”)
      @Results({
      @Result(column = “id”,property = “id”,id = true),
      @Result(column = “content”,property = “content”,jdbcType = JdbcType.OTHER,typeHandler = config.mybaits.handler.MySqlJsonHandler.class)
      })
      BaseInfoDO getById(@Param(“id”) Long id);

    @Update(“update tab_base_info set content = json_set(content,”KaTeX parse error: Can't use function '\"' in math mode at position 6: .name\̲"̲,\"小王2\",\".phone.smsc",‘2020’) where id = #{id}")
    int updateName(@Param(“id”) Long id);
    }

三 窗口函数
从 MySQL 8.0 开始,新增了一个叫窗口函数的概念,它可以用来实现若干新的查询方式。窗口函数与 SUM()、COUNT() 这种集合函数类似,但它不会将多行查询结果合并为一行,而是将结果放回多行当中。即窗口函数不需要 GROUP BY。

3.1 生成列
  生成列(generated column)的值是根据列定义中包含的表达式计算得出的。 生成列包含下面两种类型:

virtual(虚拟):当从表中读取记录时,将动态计算该列。
stored(存储):当向表中写入新记录时,将计算该列并将其存储为常规列。
  virtual生成列比stored生成列更有用,因为一个虚拟的列不占用任何存储空间。你可以使用触发器模拟stored生成列的行为。

创建表

CREATE TABLE test_user2 (
id bigint ,
first_name varchar(100),
last_name VARCHAR(100),
full_name varchar(200) as (concat(first_name, ’ ', last_name)),
sex varchar(8) DEFAULT NULL,
age TINYINT DEFAULT NULL,
phone varchar(8)
)

插入数据

INSERT INTO test_user2 (first_name,last_name,sex,age,phone) VALUES(‘王’,‘小明’,‘男’,12,’{}’);

查询数据

添加字段 虚拟字段

alter table test_user2 add birth_date_year year as (year(birthdate)) virtual;

3.2 窗口函数
ROW_NUMBER():分区内当前行的编号。
RANK():分区中当前行的等级(有间隔)。
DENSE_RANK():分区内当前行的等级(无间隔)。
PERCENT_RANK():百分比排名值。
FIRST_VALUE():窗口帧中第一行的参数值。
LAST_VALUE():窗口帧中最末行的参数值。
LEAD():领先于分区内当前行的那一行的参数值。
LAG():落后于分区内当前行的那一行的参数值。
NTH_VALUE():窗口帧中的第 n 行的参数值。
NTILE():分区内当前行的桶的编号。
COME_DIST():累积分布值。

select * from (SELECT row_number()over(partition by first_name ORDER BY birth_date_year desc) as row_num,id,first_name,last_name,full_name,age,birth_date_year from test_user2 ) t

SELECT * from test_user2 GROUP BY first_name order by birth_date_year

3.3 博客地址
https://www.cnblogs.com/DataArt/p/9961676.html
四 隐藏索引
在 MySQL 8.0 中,索引可以被“隐藏”和“显示”。当对索引进行隐藏时,它不会被查询优化器所使用。
应用场景:
  1)软删除
   删除索引,在线上,如果删除错了索引,只能通过创建索引的方式将其添加回来,对于一些大的数据库而言,是比较耗性能的;为了避免删错,可以先将其设置为不可见,优化器这时候就不会使用它,但是后台仍然在维护,确定后,再删除。

2)灰度发布
   与软删除差不多,如果想要测试一些索引的功能或者随后可能会使用到这个索引,可以先将其设置为隐藏索引,对于现有的查询不会产生影响,测试后,确定需要该索引,可以将其设置成可见索引。

3) 性能调试
我们先隐藏一个索引,然后观察其对数据库的影响。如果数据库性能有所下降,说明这个索引是有用的,然后将其“恢复显示”即可;如果数据库性能看不出变化,说明这个索引是多余的,可以考虑删掉。

创建索引

create index idx_name on test_user(name) ;

#查看执行计划

隐藏索引

alter table test_user alter index idx_name invisible;

查看执行计划

设置索引可见

alter table test_user alter index idx_name visible;

查看索引状态

#主键不可以设置为隐藏

五 降序索引
MySQL 8.0 为索引提供按降序方式进行排序的支持,在这种索引中的值也会按降序的方式进行排序

#创建升序排序表:
create table t2(c1 int,c2 int,index idx_c1_c2(c1,c2 ));

#创建降序排序表
create table t3(c1 int,c2 int,index idx_c1_c2(c1,c2 desc ));

desc 排序 查询t2

desc 排序 查询t3

降序索引的意义
如果一个查询,需要对多个列进行排序,且顺序要求不一致。在这种场景下,要想避免数据库额外的排序-“filesort”,只能使用降序索引.

虽然c1是升序索引,但在第二个查询中,对其进行降序排列时,并没有进行额外的排序,使用的还是索引。在这里,大家容易产生误区,以为升序索引就不能用于降序排列,实际上,对于索引,MySQL不仅支持正向扫描,还可以反向扫描。反向扫描的性能同样不差。

MySQL 8.0不会对group by操作进行隐式排序。Mysql8.0以前会默认进行升序排序

六 UTF-8编码
从MySQL8.0开始,使用utf8mb4 作来MySQL的默认字符集,并支持 Unicode 9,默认字符集将从 latin1 改为 utf8mb4,默认定序collation将从latin1_swedish_ci 改为 utf8mb4_800_ci_ai;

七 持久化设置
MySQL8.0 新增 SET PERSIST 的命令,该命令的配置值保存到数据目录下的mysqld-auto.cnf文件中,待重启后,读取该文件,用其中的配置覆盖缺省的配置文件,补充了SET GLOBAL 命令只能临时生效的不足;
命令的使下如:

设置持久化最大连接数

SET PERSIST max_connections = 400;

八 公共表格表达式
MySQL 8.0 新增了 CTEs 功能(Common Table Expresssions 公共表格表达式)。CTE 是一个命名的临时结果集,仅在单个 SQL 语句的执行范围内存在,可以是自引用,也可以在同一查询中多次引用。

8.1子查询
select …… from ( subquery ) as derived, table_name ……;

8.2 非递归CTE
with derived as (
subquery
)
select …… from derived, table_name ……;

8.3 递归CTE
  递归CTE是一种特殊的CTE,其子查询会引用自己的名字。WITH子句必须以WITH RECURSIVE开头。递归CTE子查询包括两部分:seed查询和recursive查询,由UNION[ALL]或UNION DISTINCT分隔。

seed select被执行一次以创建初始数据子集;
recursive select被重复执行以返回数据的子集,直到获得完整的结果集。
当迭代不会生成任何新行时,递归会停止。这对挖掘层次结构(父/子或部分/子部分)非常有用。

#创建表
CREATE TABLE operator (
id bigint(20) NOT NULL AUTO_INCREMENT,
parent_id bigint(20) DEFAULT NULL,
name varchar(255) DEFAULT NULL,
gmt_create datetime DEFAULT NULL,
gmt_modified datetime DEFAULT NULL,
PRIMARY KEY (id)
)

查询数据

#递归cte查询
WITH recursive operator_tree ( id, name, path ) AS (
SELECT
a.id,
a.name,
cast( a.id AS CHAR ( 200 ) )
FROM

operator a 
WHERE
a.parent_id = 0

UNION ALL
SELECT
b.id,
b.name,
concat( c.id, ‘->’, b.id ) AS path
FROM
operator b
JOIN ( SELECT e.id FROM operator e WHERE e.parent_id = 0 ) c ON b.parent_id = c.id
) SELECT
*
FROM
operator_tree;

递归结果

九 innodb select for update 跳过锁等待

select … for update,select … for share(8.0新增语法) 添加 NOWAIT、SKIP LOCKED语法,跳过锁等待,或者跳过锁定。

在5.7及之前的版本,select…for update,如果获取不到锁,会一直等待,直到innodb_lock_wait_timeout超时。

在8.0版本,通过添加nowait,skip locked语法,能够立即返回。

如果查询的行已经加锁,那么nowait会立即报错返回,

而skip locked也会立即返回,只是返回的结果中不包含被锁定的行。

执行nowait

#执行skip locked

十 账户安全

10.1.用户的创建与授权

1.用户的创建与授权

在MySQL5.7的版本:

> grant all privileges on . to ‘用户名’@‘主机’ identified by ‘密码’;

在MySQL8.0需要分开执行:

>create user ‘用户名’@‘主机’ identified by ‘密码’;

>grant all privileges on . to ‘用户名’@‘主机’;

用以前的一条命令在8.0里面创建用户,会出现sql语法错误

10.2.认证插件更新

MySQL5.7默认身份插件是mysql_native_password

MySQL8.0默认的身份插件是caching_sha2_password
  查看身份认证插件命令:show variables like ‘default_authentication_plugin%’;
  身份认证插件可以通过以下2中方式改变:    1)系统变量default_authentication_plugin去改变,在my.ini文件的[mysqld]下面设置default_authentication_plugin=mysql_native_password即可
  2)如果希望只是某一个用户通过mysql_native_password的方式认证,可以修改数据库mysql下面的user表的字段,执行以下命令:  >alter user ‘用户名’@‘主机’ identified width mysql_native_password by ‘密码’;

10.3 密码管理
MySQL8.0的密码管理策略有3个变量

password_history 修改密码不允许与最近几次使用或的密码重复,默认是0,即不限制
  
  password_reuse_interval 修改密码不允许与最近多少天的使用过的密码重复,默认是0,即不限制
  password_require_current 修改密码是否需要提供当前的登录密码,默认是OFF,即不需要;如果需要,则设置成ON

查询当前MySQL密码管理策略相关变量,使用以下命令:
  
  >show variables like ‘password%’;

1)设置全局的密码管理策略,在my.ini配置文件中,设置以上3个变量的值这种设置方式,需要重启mysql服务器;某些生产环境不允许重启,MySQL8.0提供了关键字persist,持久化,执行以下命令:

>set persist password_history=6;

这条命令会在数据目录下生成新的配置文件(/var/lib/mysql/mysqld-auto.cnf),下次服务器重启的时候除了读取全局配置文件,还会读取这个配置文件,这条配置就会被读入从而达到持久化的目的
  2)针对某一个用户单独设置密码管理策略

>alter user ‘用户名’@‘主机’ password history 5;

这样,这个用户的password_history 就被设置成了5,查看一下:

>show user,host,Password_reuse_history from user;
  
  查看某一张的字段的所有字段,使用以下命令:

>desc 表名;

10.4 角色管理
角色:一组权限的集合
  
  一组权限赋予某个角色,再把某个角色赋予某个用户,那用户就拥有角色对应的权限
  
  1)创建一个角色
  >create role ‘角色1’;
  
  2)为这个角色赋予相应权限
  >grant insert,update on . to ‘角色1’;
  
  3)创建一个用户
  >create user ‘用户1’ identified by ‘用户1的密码’;
  
  4)为这个用户赋予角色的权限
  >grant ‘角色1’ on . to ‘用户1’;

执行完上面4步,用户1就拥有了插入与更新的权限
  
  5)再创建1个用户
  >create user ‘用户2’ identified by ‘用户2的密码’;
  
  6)为这个用户赋予同样的角色
  >grant ‘角色1’ on . to ‘用户2’;
  
  执行完上面2步,用户2也用了角色1的权限,即插入与更新

查看用户权限,执行以下命令:
  >show grants for ‘用户名’;

7)启用角色,设置了角色,如果不启用,用户登录的时候,依旧没有该角色的权限
  >set default role ‘角色名’ to ‘用户名’;

8)如果一个用户有多个角色,使用以下命令
  >set default role all to ‘用户名’;

MySQL中与用户角色相关的表:mysql.default_roles、mysql.role_edges,有兴趣的朋友可以进去查看下。

9)撤销权限
  >revoke insert,update on . from ‘角色名’;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值