MySQL day03

MySQL day03

1 SQL分类

  1. DQL(Data Query Language)

    数据查询语言:对数据库中数据执行查询操作的SQL。

  2. DCL(Data Control Language)

    数据控制语言:对数据库用户设定以及更改权限的SQL。

  3. DDL(Data Definition Language)

    数据定义语言:执行表、序列、视图、索引的创建和销毁工作的SQL。

  4. DML(Data Manipulation Language)

    数据操作语言:执行数据的增、删、改工作的SQL。

  5. TCL(Transaction Control Lanager)

    事务控制语言:控制数据库事务的SQL。

DQL在之前的学习中已经学习过了,DCL主要是有关权限操作的语句(实际生产中通常由DBA使用),接下来我们要学习的是DDL、DML和TCL。

2 DDL

3.1 数据库的创建和销毁

MySQL中通过库管理不同项目的表。

  1. 创建数据库

    语法: create database [if not exists] 数据库名 [default charset 字符集]
    示例:
    create database test;--创建数据库
    create database if not exists test;--如果不存在test库,则创建数据库;否则什么都不做
    --创建数据库,默认编解码集为utf8mb4
    create database if not exists test default charset utf8mb4;
    
  2. 销毁数据库

    语法:drop database [if exists] 数据库名;
    示例:
    drop database test;--删除数据库
    drop database if exists test;--如果数据库存在,则删除数据库
    

3.2 表和创建和销毁

表是数据库组织和存储数据的基本单位。表主要就是由一个个字段(列)组成。

3.1.1 表的创建
语法:
create table [if not exists] 表名(
  字段名 数据类型  [约束],
  字段名 数据类型  [约束],
    ...
);
  1. 表名和字段名

    合法的标识符即可。
    表名一般以t_开头,字段名多个单词间以下划线分隔。
    表名和字段名不区分大小写。

  2. 数据类型

    明确一列可以存储什么样的数据。

    数据类型解释注意事项
    tinyint1字节整数有符号数:-128~127
    无符号数(unsigned):0~255
    smallint2字节整数有符号数:-32768~32767
    无符号数:0~65535
    mediumint3字节整数有符号数:-8833608~8833607
    无符号数:0~1677215
    int、integer4字节整数有符号数:-2147483648~2147483647
    无符号数:0~4294967295
    bigint8字节整数有符号数:-9223372036854775808~9223372036854775807
    无符号数:0~18446744073709551615
    float4字节浮点数-3.402823466E+38~3.402823466E+38
    double8字节浮点数-1.7976931348623157E+308~1.7976931348623157E+308
    decimal(m,d)m+2个字节,定点数m表示精度(数字有效长度),d表示标度(小数点的位数)
    m最大值65,默认值10;d最大值30,默认值0
    char(n)定长字符串无论保存的数据多少,一定占n的字符空间,n最大255
    varchar(n)变长字符串根据保存的数据多少,占据对应的字符空间,n最大65535
    text大文本类型能保存4G大小文字
    enum枚举类型在给定的范围内选择一个值,比如性别 enum(‘F’,‘M’)
    date4字节包含年月日,1000-01-01~9999-12-31
    time3字节包含时分秒,-838:59:59~838:59:59
    datetime8字节包含年月日 时分秒,1000-01-01 00:00:00~9999-12-31 23:59:59
    timestamp4字节包含年月日时分秒,1970-01-01 08:00:01~2038-01-19 11:14:07

    实战建议:

    • 如果数字一定大于0,且不会进行减运算,可以使用unsigned无符号数。如非必要,还是建议使用有符号数。
    • float和double存在精度问题,实战中很少使用,MySQL后续版本将不再支持上述两个类型。对精度要求较高时使用decimal。
    • char和varchar在保存多字节字符(比如中文)底层实现是一样的,所以实战中建议使用varchar。
    • 实战中通常需要精确到秒,而timestamp的上限很快到达,建议使用datetime

    总结需要掌握的类型:

    整数:int bigint
    小数:double、decimal
    字符:varchar
    日期:datetime

    create table t_person(
          person_id int,
          person_name varchar(50),
          age tinyint unsigned,
          sex enum('F','M'),
          birthday datetime,
          salary decimal(10,2),
          mobile varchar(11),
          address varchar(500)
    );
    
  3. 约束

    约束限制字段值格式和范围。

    约束解释说明
    primary key主键用来明确一列为主键列
    not null非空约束一列的值不能为null
    unique唯一约束一列的值不能重复
    default默认当列没有值时,设置默认值
    references外键约束明确该列为外键列,并指明引用哪一张表的哪一列值

    普通约束示例:

    --列级约束:直接将约束定义在列中
    create table t_person(
          person_id int primary key,
          person_name varchar(50) unique not null,
          age tinyint unsigned not null,
          sex enum('F','M') not null default 'M',
    	  birthday datetime not null,
    	  salary decimal(10,2) not null,
          mobile varchar(11) not null,
          address varchar(500) not null
    );
    
    --表级约束:将约束定义在列定义语句后,not null、default 没有表级约束
    create table t_person(
          person_id int ,
          person_name varchar(50) ,
          age tinyint unsigned ,
          sex enum('F','M') not null default 'M',
    	  birthday datetime not null,
    	  salary decimal(10,2) not null,
          mobile varchar(11) not null,
          address varchar(500) not null,
        -- [constraint 约束名] 约束类型(字段名)
    	  constraint pk_person_id primary key(person_id),
    	  constraint uq_person_name unique(person_name)
    );
    

    外键约束示例:

    --外键约束,必须使用表级约束方式定义
    create table t_class(
    	class_id int primary key,
    	class_name varchar(20) not null
    );
    
    create table t_student(
    	student_id int primary key,
    	student_name varchar(20) not null,
    	class_id int not null,
    	constraint fk_student_class foreign key(class_id) references t_class(class_id)
    )
    
3.1.2 表的销毁
语法:
drop table [if exists] 表名;
示例:
drop table t_person;
注意:如果两张表有外键引用关系,那么必须先删子表,后删父表。

3.3 视图

视图:一个视图代表一个复杂的查询SQL,基于视图操作就是基于它指代的查询SQL进行操作。

3.3.1 创建视图
语法:
create view 视图名  as  查询SQL;
示例:
create view v_employee_departments as 
select e.*,d.department_name,d.location_id 
from employees e left join departments d 
on e.department_id = d.department_id;
3.3.2 使用视图
语法:
select 列,列,...
from 视图名
[where 条件]
...

示例:
create view v_employee_departments as 
select e.*,d.department_name,d.location_id 
from employees e left join departments d 
on e.department_id = d.department_id;
3.3.3 销毁视图
语法:
drop view 视图名;
示例:
drop view v_employee_departments;
3.3.4 视图的特点
  • 视图本质上就是一个复杂的查询SQL
  • 视图本身并不能提升查询效率,只能提升开发效率
  • 视图本身不是表,不存储任何数据
  • 视图本身还可以用于屏蔽底层表的一些机密列

3.4 索引

索引:索引是数据库为提高查询速度而提供一种机制。

从数据库中查询数据和从字典中查询一个字的过程相似。数据库中的索引和字典中的拼音、偏旁部首、笔画这些组成类似,用来提高查询效率的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ZrNDSHd-1631064851492)(MySQL day03.assets/image-20210516215230675.png)]

3.4.1 索引语法
语法:
创建:create index 索引名 on 表名(列名);
查看:show index from 表名;
删除索引:drop index 索引名 on 表名;
3.4.2 使用索引
当使用添加了索引的列作为查询条件时,数据库会自动使用索引。
提前准备千万级的数据能看出索引的效果。
3.4.3 索引的特点
  • 索引用来提高查询效率
  • 索引也会占用磁盘空间
  • 索引不是越多越好,一般每张表不要超过5个。原因:1.索引会占空间 2.影响增删改的效率
  • 注意,索引不是任何时候都有效,例如在is null或者模糊查询时索引会失效
3.4.4 InnoDB的索引模型

MySQL5.5后默认使用的是InnoDB存储引擎。在InnoDB中,表中的数据都是根据主键索引以树的形式存放的,非叶子节点保存主键值,所有的行都在叶子节点上,这种存储方式的表称为索引组织表。

create table t_index(
id int primary key, 
k int not null, 
name varchar(16),
index (k)--为k字段建立索引
)

insert into t_index values(100,1,'xiao1hei');
insert into t_index values(200,2,'xiao2hei');
insert into t_index values(300,3,'xiao3hei');
insert into t_index values(500,5,'xiao5hei');
insert into t_index values(600,6,'xiao6hei');

上述t_index表有主键索引和普通索引共2个索引,2棵索引树如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-722uMA8f-1631064851493)(MySQL day03.assets/image-20210505204317892.png)]

从图中不难看出,根据叶子节点的内容,索引类型分为主键索引和非主键索引。

  • 主键索引:主键索引也被称为聚簇索引,主键索引的叶子节点存的是整行数据。
  • 非主键索引:非主键索引也被称为二级索引,非主键索引的叶子节点内容是主键的值。

基于主键索引和普通索引的查询有什么区别?

  • 如果语句是select * from t_index where id=500,即主键查询方式,则只需要搜索id这棵B+树;
  • 如果语句是select * from t_index where k=5,即普通索引查询方式,则需要先搜索k索引树,得到id的值为500,再到ID索引树搜索一次。这个过程称为回表。

4 DML(Data Manipulation Language)

数据操纵语言:对表中的数据执行增、删、改以的SQL。

4.1 添加

语法:
insert into 表名(列名,列名,列名,...) 
values(值,值,值,...);

示例:
insert into t_person(person_id,person_name,age,sex,birthday,salary,mobile,address)
values(1,'xiaohei',18,'M','2000-12-23 12:30:30',10000.00,'187xxxxxxx','郑州硅谷');
注意:values后小括号中的值要和表名后小括号对应!!!

--给所有列添加数据,表名后的小括号可以省略。注意,此时值就要和表定义时列的顺序保持一致!!!
insert into 表名
values(值,值,值,...);
示例:
insert into t_person
values(2,'xiaobai',18,'F','2000-12-23 12:30:30',12000.00,'185xxxxxxx','郑州硅谷');

--主键自增,将主键设置为auto_increment,主键的值无需显式赋值可自动增长
create table t_person(
      person_id int primary key auto_increment,
      person_name varchar(50) unique not null,
      age tinyint unsigned not null,
      sex enum('F','M') not null default 'M',
	  birthday datetime not null,
	  salary decimal(10,2) not null,
      mobile varchar(11) not null,
      address varchar(500) not null
);

insert into t_person
values(null,'xiaolv',20,'F','2000-12-23 12:30:30',12000.00,'186xxxxxxx','郑州硅谷');

4.2 删除

语法:
delete from 表名
[where 条件];
示例:
delete from t_person
where person_id = 1;
注意:不加条件,则删除表中所有数据。

表截断:truncate table 表名;//删除表中所有数据
表截断:直接在物理空间中,将保存数据的空间截断,效率更高
delete from 表:一行一行的删除,效率比较低。

4.3 更改

语法:
update 表名 
set 列名 = 新值,列名=新值,...
[where 条件];
示例:
update t_person
set age = 20,sex = 'F'
where person_id = 1;

注意:不加where条件,则更新所有行。

5 TCL 事务

事务:事务是数据库为保证SQL操作完整性而提供的一种机制。保证一个业务对应的多条SQL要么同时成功,要么同时失败。

5.1 使用事务

开启事务 
begin 或者 start transaction; 
第1条sql
第2条sql
...

结束事务,如果结果正确:提交事务  commit
        如果结果错误:回滚事务  rollback
        
示例:
begin;
update t_account set balance = balance - 100 where account_name='xushy';
update t_account set balance = balance + 100 where account_name='liy';
成功:commit;
失败:rollback;

5.2 事务的特点和隔离级别

在SQL92中定义了事务的4个特点:ACID

  • Atomicity 原子性 保证多条SQL要么同时成功,要么同时失败。(这是事务最直观的特性,上面的案例体现的就是这一点)
  • Consistency 一致性 事务执行前后,数据的状态是一致的,是正确的。典型场景:一个账户同时被老公和老婆操作,老公存钱、老婆花钱,结果一定得是正确的。
  • Isolation 隔离性 并发访问同一数据时,不同用户是否可以看到另外一个用户对数据的变化的程度。oracle默认只能看到另外一个用户提交后的修改。
  • Durability 持久性 一个事务一旦提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响 。

其中原子性是最直观的,持久性更多的在数据库宕机重启数据恢复和数据备份时体现,隔离性指的是并发场景下多用户操作相同数据时的表现出来的相互关系。一致性,是一个综合性的规定,或者说是一个把握全局的规定。因为它是由原子性、持久性、隔离性共同保证的结果,而不是单单依赖于某一种技术。

在开发层面相关联的主要是原子性和隔离性。原子性已经看过,下面我们一起看一下隔离性。

5.2.1 并发事务问题

隔离性在数据库的并发访问时得以体现,随着数据库并发事务处理能力的大大增强,数据库资源的利用率也会大大提高,从而提高了数据库系统的事务吞吐量,可以支持更多的用户并发访问。但并发事务处理也会带来一些问题,如:脏读、不可重复读、幻读。这些问题是和隔离性相伴相生的。下面一一解释其含义。

  • 脏读

    B事务正在对一条记录做修改,在这个事务提交前,这条记录的数据就处于不一致状态;这时,另一个事务A也来读取同一条记录,如果不加控制,第二个事务读取了这些未提交的(“脏”)数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象的叫作"脏读"(Dirty Reads)。

  • 不可重复读

    一个事务中多次执行相同的查询SQL,不同时刻读取的数据不同。要么发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫作“ 不可重复读”(Non-Repeatable Reads)。

  • 幻读

    一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”(Phantom Reads)。

5.2.2 隔离级别

上述的问题可以通过设置不同的隔离级别解决,SQL92中明确了4种隔离级别,不同的级别有不同的特点。

隔离级别脏读不可重复度幻读
READ-UNCOMMITTED可能可能可能
READ-COMMITTED不可能可能可能
REPEATABLE-READ不可能不可能可能(MySQL不可能)
SERIALIZABLE不可能不可能不可能

注:上表中的可能是严谨的说法,可以理解为基本就是存在问题,不可能就是一定不存在问题的。

数据库隔离级别的支持:

  • Oracle:只支持READ-COMMITTED和SERIALIZABLE 2种隔离级别。
  • MySQL:MySQL支持4种,MySQL默认隔离级别是REPEATABLE-READ。

实战时,大多数场景使用读已提交就足够了。

5.2.3 MySQL下演示隔离级别

MySQL支持多种存储引擎:InnoDB(支持事务)、MyISAM、MEMORY

存储引擎:决定了数据库如何的保存管理数据。

  1. 确认MySQL使用的存储引擎
show engines;//查询数据库支持的存储引擎
show variables like 'default_storage_engine';//查询默认引擎

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bGMK8OT3-1631064851493)(MySQL day03.assets/image-20200406163015651.png)]

  1. 查询当前使用的隔离级别:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y9aAM4mv-1631064851494)(MySQL day03.assets/image-20200406163149179.png)]

  2. 修改当前使用的隔离级别:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cbtuNZT5-1631064851494)(MySQL day03.assets/image-20200406163503131.png)]

  3. MySQL中开启事务和结束事务

    >start transaction;//开启事务
    >commit;//提交
    >rollback;//回滚
    

隔离级别

准备工作:

create table t_account(
	id int primary key,
    money double
);
start transaction;
insert into t_account values(1,100);
insert into t_account values(2,200);
commit;
  1. 读未提交隔离级别(脏读问题)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8l6u26g9-1631064851495)(MySQL day03.assets/image-20200406170439133.png)]

    脏读:B事务未提交,A事务可以读取到B事务插入的数据

  2. 读提交隔离级别(解决脏读问题,但存在不可重复读和幻读的问题)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YK7IY3Ix-1631064851495)(MySQL day03.assets/image-20210508221628304.png)]

    B事务不提交,A事务读取不到。B事务提交后A事务就可以读取到。

    仍存在的问题:不可重复读和幻读

  3. 可重复读隔离级别(解决了不可重复读以及幻读)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y86t1BEk-1631064851496)(MySQL day03.assets/image-20210509185633571.png)]

  4. 序列化读

    串行,并发最差。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kY5BupGN-1631064851496)(MySQL day03.assets/image-20200406171658872.png)]

5.3 事务的实现原理

事务的实现非常复杂,MySQL不同的版本一些实现细节都会有差异,在这里我们主要介绍事务背后的核心组件和工作流程。

我们通过一个典型场景,介绍事务相关的日志和工作流程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YuW2u3RL-1631064851497)(MySQL day03.assets/image-20210509214204879.png)]

  • redo log

    在InnoDB存储引擎中,为了提高效率,事务中的修改操作不会直接操作磁盘中的表数据,都会将最新的修改先写⼊redo log中,等待系统空闲时,再将redo log中记录的修改持久化到表中。

    也就是说数据库中的磁盘中的表并不是完整的数据,要再加上redo log记录的修改,才是完整一致的数据。当MySQL发生故障重启的时候,根据 redo log进⾏恢复(重做),从⽽保证了数据的完整性,也就是事务的持久性。

    注意:redo log日志空间有限,是循环写的。也就是当空间不足时会从头部重新写从而复用空间。

  • binlog

    在commit事务时,将redo log中记录的修改保存到binlog中。binlog和redolog最大的区别时binlog是追加写的,理论上文件空间没有限制,记录了数据库一段时间内所有的写操作(增、删、改)。

    binlog可以用于主从复制、数据恢复等场景,也是事务持久性的保障之一。

  • undo log

    undo log(撤销日志),当一个事务中执行了修改操作时,除了在redo log中记录修改,还会在undo log中记录一个反向操作,比如 执⾏⼀个delete操作,undo log就会记录⼀个insert操作 ;执⾏⼀个insert操作,undo log就会记录⼀个delete操作;执⾏⼀个update操作,undo log就会记录⼀个相反的update操作。

    一个事务中执行多个修改,最终没有commit而是rollback,那就可以根据undo log日志的记录反向得到原来的数据,这就保证了原子性。
    当一个事务的修改没有提交,另外一个事务执行查询,也是根据undo log日志反向计算出原来的数据,以保证第2个事务的隔离性。

重点:

  1. 表的创建

    1. 建表的基本语法create table 表名…
    2. 数据类型 int 、bigint、double、decimal、varchar、datetime
    3. 约束 primary key not null unique
  2. DML

    1. 添加 insert into
    2. 删除 delete from
    3. 更新 update
  3. 事务

    基本用法:

    begin;
    多条sql
    commit; 成功
    rollback;失败
    

do log就会记录⼀个insert操作 ;执⾏⼀个insert操作,undo log就会记录⼀个delete操作;执⾏⼀个update操作,undo log就会记录⼀个相反的update操作。

一个事务中执行多个修改,最终没有commit而是rollback,那就可以根据undo log日志的记录反向得到原来的数据,这就保证了原子性。
当一个事务的修改没有提交,另外一个事务执行查询,也是根据undo log日志反向计算出原来的数据,以保证第2个事务的隔离性。

重点:

  1. 表的创建

    1. 建表的基本语法create table 表名…
    2. 数据类型 int 、bigint、double、decimal、varchar、datetime
    3. 约束 primary key not null unique
  2. DML

    1. 添加 insert into
    2. 删除 delete from
    3. 更新 update
  3. 事务

    基本用法:

    begin;
    多条sql
    commit; 成功
    rollback;失败
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值