MySQL笔记2

news2024/12/25 9:30:24

MySQL笔记2

    • 一、CRUD操作
      • 1.修改数据:update
      • 2.删除数据:delete
    • 二、数据库中表的约束
      • 1.非空约束 not null
      • 2.唯一性约束 unique
      • 3.主键约束 primary key
      • 4.外键约束
    • 三、索引
      • 1**什么是索引**?
      • 2**MySQL中最经典的两种存储引擎**
      • 3**为何需要索引**?
      • 案例
      • 4设置索引
      • @不普通的索引有哪些?
      • 5查看、删除索引
      • 6索引背后的数据结构
        • B-树
        • B-树的特点
        • 聚簇索引和非聚簇索引
        • B+树
    • 四、事务
      • 1.什么是事务
      • 2.事务的四大特性
        • ps.并发与并行
        • 问题
        • 事务的三个操作
      • 3.MySQL事务的四种隔离级别
        • 级别
        • 举例
        • 演示

一、CRUD操作

MySQL数据库中包含四种操作:

Create(增) Retrieve(检索) Update(修改) Delete(删除)

1.修改数据:update

这也是一行一行的更新的

update 表名 set 字段1=1,字段2=2... where 条件;

注意:没有条件整张表数据全部更新。

select * from t_xueke;

alter table t_xueke add 学科类型 varchar(255);

select * from t_xueke;
+-----+---------+----------+
| xno | subject | 学科类型 |
+-----+---------+----------+
|   1 | 数学    | NULL     |
|   2 | 英语    | NULL     |
|   3 | 语文    | NULL     |
|   4 | 武术    | NULL     |
|   5 | 唱歌    | NULL     |
|   6 | 舞蹈    | NULL     |
|   7 | 篮球    | NULL     |
|   8 | NULL    | NULL     |
+-----+---------+----------+

将科目为数学英语语文的学科类型修改为默认

不管等于号(=)后面跟的是英文或是中文,都必须加单引号

update t_xueke set 学科类型='默认' where subject in('语文', '数学', '英语');

select * from t_xueke;
+-----+---------+----------+
| xno | subject | 学科类型 |
+-----+---------+----------+
|   1 | 数学    | 默认     |
|   2 | 英语    | 默认     |
|   3 | 语文    | 默认     |
|   4 | 武术    | NULL     |
|   5 | 唱歌    | NULL     |
|   6 | 舞蹈    | NULL     |
|   7 | 篮球    | NULL     |
|   8 | NULL    | NULL     |
+-----+---------+----------+

更新所有记录

create table xueke (select * from t_xueke);
select * from xueke;
+-----+---------+----------+
| xno | subject | 学科类型 |
+-----+---------+----------+
|   1 | 数学    | 默认     |
|   2 | 英语    | 默认     |
|   3 | 语文    | 默认     |
|   4 | 武术    | NULL     |
|   5 | 唱歌    | NULL     |
|   6 | 舞蹈    | NULL     |
|   7 | 篮球    | NULL     |
|   8 | NULL    | NULL     |
+-----+---------+----------+

update xueke set subject = 'x', 学科类型='y';
select * from xueke;
+-----+---------+----------+
| xno | subject | 学科类型 |
+-----+---------+----------+
|   1 | x       | y        |
|   2 | x       | y        |
|   3 | x       | y        |
|   4 | x       | y        |
|   5 | x       | y        |
|   6 | x       | y        |
|   7 | x       | y        |
|   8 | x       | y        |
+-----+---------+----------+

2.删除数据:delete

这是一行一行的删除的

delete from 表名 where 条件;

注意:没有条件时全部删除。

drop table xueke;
create table xueke (select * from t_xueke);
+-----+---------+----------+
| xno | subject | 学科类型 |
+-----+---------+----------+
|   1 | 数学    | 默认     |
|   2 | 英语    | 默认     |
|   3 | 语文    | 默认     |
|   4 | 武术    | NULL     |
|   5 | 唱歌    | NULL     |
|   6 | 舞蹈    | NULL     |
|   7 | 篮球    | NULL     |
|   8 | NULL    | NULL     |
+-----+---------+----------+

删除数学学科数据?
delete from xueke where subject='数学';
+-----+---------+----------+
| xno | subject | 学科类型 |
+-----+---------+----------+
|   2 | 英语    | 默认     |
|   3 | 语文    | 默认     |
|   4 | 武术    | NULL     |
|   5 | 唱歌    | NULL     |
|   6 | 舞蹈    | NULL     |
|   7 | 篮球    | NULL     |
|   8 | NULL    | NULL     |
+-----+---------+----------+

删除所有数据?
delete from xueke;
Empty set (0.00 sec)

怎么删除大表中的数据?(重点)
truncate table 表名;
// 表被截断,不可回滚。永久丢失。

create table xueke2(select * from t_xueke);
truncate table xueke2;
mysql> show tables;
+-----------------+
| Tables_in_study |
+-----------------+
| t_indentity     |
| t_student       |
| t_xueke         |
| xueke           |
| xueke2          |
+-----------------+
5 rows in set (0.01 sec)
mysql> select * from xueke2;
Empty set (0.00 sec)


删除表?
drop table 表名; // 这个通用。
drop table if exists 表名; // oracle不支持这种写法。

二、数据库中表的约束

创建表的时候,可以给表的字段添加相应的约束,添加约束的目的是为了保证表中数据的

合法性、有效性、完整性

常见的约束有哪些呢?

非空约束(not null):约束的字段不能为NULL

唯一约束(unique):约束的字段不能重复

主键约束(primary key):约束的字段既不能为NULL,也不能重复(简称PK)

外键约束(foreign key):…(简称FK)

检查约束(check):注意Oracle数据库有check约束,但是mysql没有,目前mysql不支持该约束。

1.非空约束 not null

  drop table if exists t_user;

  create table t_user(

    id int,

    username varchar(255) not null,

    password varchar(255)

  );

  insert into t_user(id,password) values(1,'123');

  ERROR 1364 (HY000): Field 'username' doesn't have a default value



  insert into t_user(id,username,password) values(1,'lisi','123');

2.唯一性约束 unique

唯一约束修饰的字段具有唯一性,不能重复。但可以为NULL。

也就是说可以不设置这个字段的值,默认值为NULL,

此时不会认为是重复数据,都是空而已

(1)给某一列增加unique约束

drop table if exists t_user;

create table t_user(
	id int,
    username varchar(255) unique
);
insert into t_user values(1,'zhangsan');
insert into t_user values(2,'zhangsan');
ERROR 1062 (23000): Duplicate entry 'zhangsan' for key 'username'

insert into t_user(id)
values
(2),(3),(4);
select * from t_user;
+------+----------+
| id   | username |
+------+----------+
|    1 | zhangsan |
|    2 | NULL     |
|    3 | NULL     |
|    4 | NULL     |
+------+----------+

(2)给两个列或多个列增加unique约束

drop table if exists t_user;
create table t_user(

	id int, 

	usercode varchar(255),

	username varchar(255),

	unique(usercode,username)

);
insert into t_user values(1,'111','zs');
insert into t_user values(2,'111','ls');
insert into t_user values(3,'222','zs');
select * from t_user;
+------+----------+----------+
| id   | usercode | username |
+------+----------+----------+
|    1 | 111      | zs       |
|    2 | 111      | ls       |
|    3 | 222      | zs       |
+------+----------+----------+
insert into t_user values(4,'111','zs');
ERROR 1062 (23000): Duplicate entry '111-zs' for key 'usercode'
-- 列级约束:包含在列定义中,直接跟在该列的其它定义之后 ,用空格分隔,不必指定列名  

-- 表级约束:与列定义相互独立,不包含在列定义中;与定义用‘,’分隔;必须指出要约束的列的名称

注意:只有主键、外键、唯一、检查 四种约束可以定义表级约束

列级约束:只能应用于一列上。
表级约束:可以应用于一列上,也可以应用在一个表中的多个列上。

即:如果你创建的约束涉及到该表的多个属性列,则必须创建的是表级约束(必须定义在表级上);

否则既可以定义在列级上也可以定义在表级上此时只是SQL语句格式不同而已

3.主键约束 primary key

主键的特点:不能为NULL,也不能重复。

主键相关的术语
     主键约束 : primary key
     主键字段 : id字段添加primary key之后,id叫做主键字段
     主键值 : id字段中的每一个值都是主键值。

主键有什么作用?

​ 表的设计三范式中有要求,第一范式就要求任何一张表都应该有主键

​ 主键的作用:主键值是这行记录在这张表当中的唯一标识。(就像一个人的身份证号码一样。)

​ 主键的分类?
​ 1.根据主键字段的字段数量来划分:
单一主键(推荐的,常用的。)
​ 复合主键(多个字段联合起来添加一个主键约束)(复合主键不建议使用,因为复合主键违背三范式。)
​ 2.根据主键性质来划分:
自然主键:主键值最好就是一个和业务没有任何关系的自然数。(这种方式是推荐的)
​ 业务主键:主键值和系统的业务挂钩,例如:拿着银行卡的卡号做主键,拿着身份证号码作为主键。(不推荐用)
​ 最好不要拿着和业务挂钩的字段作为主键。因为以后的业务一旦发生改变的时候,主键值可能也需要随着发生变化,但有的时候没有办法变化,因为变化可能会导致主键值重复。

一张表的主键约束只能有1个。
  • 使用表级约束方式定义主键:

    ```sql
    drop table if exists t_user;
      create table t_user(
      	id int,
      	username varchar(255),
          primary key(id)
    );
    insert into t_user(id,username) values(1,'zs');
    insert into t_user(id,username) values(2,'ls');
    insert into t_user(id,username) values(3,'ws');
    insert into t_user(id,username) values(4,'cs');
    select * from t_user;
    +----+----------+
    | id | username |
    +----+----------+
    |  1 | zs       |
    |  2 | ls       |
    |  3 | ws       |
    |  4 | cs       |
    +----+----------+
                    
    insert into t_user(id,username) values(4,'cx');
    ERROR 1062 (23000): Duplicate entry '4' for key 'PRIMARY'
    ```
    

mysql提供主键值自增:(非常重要。)

drop table if exists t_user;

create table t_user(

	id int primary key auto_increment, // id字段自动维护一个自增的数字,从1开始,以1递增。

	username varchar(255)

);

4.外键约束

关于外键约束的相关术语:

​ 外键约束: foreign key

​ 外键字段:添加有外键约束的字段

​ 外键值:外键字段中的每一个值。

业务背景:

请设计数据库表,用来维护学生和班级的信息?

第一种方案:一张表存储所有数据

​ no(pk) name classno classname

​ -------------------------------------------------------------------------------------------

​ 1 zs1 101 北京大兴区经济技术开发区亦庄二中高三1班

​ 2 zs2 101 北京大兴区经济技术开发区亦庄二中高三1班

​ 3 zs3 102 北京大兴区经济技术开发区亦庄二中高三2班

​ 4 zs4 102 北京大兴区经济技术开发区亦庄二中高三2班

​ 5 zs5 102 北京大兴区经济技术开发区亦庄二中高三2班

​ 缺点:冗余。【不推荐】

第二种方案:两张表(班级表和学生表)

​ t_class 班级表

​ cno(pk) cname

​ --------------------------------------------------------

​ 101 北京大兴区经济技术开发区亦庄二中高三1班

​ 102 北京大兴区经济技术开发区亦庄二中高三2班

​ t_student 学生表

​ sno(pk) sname classno(该字段添加外键约束fk)

​ ------------------------------------------------------------

​ 1 zs1 101

​ 2 zs2 101

​ 3 zs3 102

​ 4 zs4 102

​ 5 zs5 102

t_student中的classno字段引用t_class表中的cno字段

此时t_student表叫做子表。t_class表叫做父表

顺序要求:

删除数据的时候,先删除子表,再删除父表。

添加数据的时候,先添加父表,在添加子表。

创建表的时候,先创建父表,再创建子表。

删除表的时候,先删除子表,在删除父表。

建表:

drop table if exists t_student;

drop table if exists t_class;


create table t_class(

	cno int,

	cname varchar(255),

	primary key(cno)

);



create table t_student(

	sno int,

	sname varchar(255),

	classno int,

	primary key(sno),

	foreign key(classno) references t_class(cno)

);


insert into t_class values(101,‘xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’);

insert into t_class values(102,‘yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy’);

insert into t_student values(1,‘zs1’,101);

insert into t_student values(2,‘zs2’,101);

insert into t_student values(3,‘zs3’,102);

insert into t_student values(4,‘zs4’,102);

insert into t_student values(5,‘zs5’,102);

insert into t_student values(6,‘zs6’,102);

select * from t_class;
+-----+-----------------------------------------------+
| cno | cname                                         |
+-----+-----------------------------------------------+
| 101 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
| 102 | yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy  |
+-----+-----------------------------------------------+

select * from t_student;
+-----+-------+---------+
| sno | sname | classno |
+-----+-------+---------+
|   1 | zs1   |     101 |
|   2 | zs2   |     101 |
|   3 | zs3   |     102 |
|   4 | zs4   |     102 |
|   5 | zs5   |     102 |
|   6 | zs6   |     102 |
+-----+-------+---------+

insert into t_student values(7,'lisi',103);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`study`.`t_student`, CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`classno`) REFERENCES `t_class` (`cno`))

ps:

1.外键值可以为NULL吗?外键值可以为NULL

2.外键字段引用其他表的某个字段的时候,被引用的字段必须是主键吗?

注意:被引用的字段不一定是主键,但至少具有unique约束。

三、索引

1什么是索引

MySQL中的索引和事务(比较复杂的场景和比较庞大的数据量),面试必考,现阶段还没有合适场景去体会用法。

=>背诵

索引是一种特殊的文件,包含数据库中所有记录的引用,类似于数组的引用下标,通过这个下标就能拿到数组中的数据。

和数组中下标一样,通过下标寻找数组数据很快捷、准确

通过索引去查找数据库中的数据也是很快的~~

MySQL数据库采用插件式设计,每种索引在不同的存储引擎中的实现都有可能不同。

-- 存储引擎:就是MySQL到底如何对数据进行增删查改的不同实现方案 ~~

例:同一种汽车品牌可能有多种车型。

汽车品牌相当于MySQL、多种车型就相当于存储引擎

2MySQL中最经典的两种存储引擎

MyISAM:MySQL5.5之前的默认存储引擎,不支持事务

InnoDB:MySQL5.5之后的存储引擎,支持事务,性能不如MyISAM

接下来关于索引和事务的实现都是基于InnoDB引擎

查询当前存储引擎

show variables like 'default_storage_engine';
+------------------------+--------+
| Variable_name          | Value  |
+------------------------+--------+
| default_storage_engine | InnoDB |
+------------------------+--------+
1 row in set, 1 warning (0.02 sec)

请添加图片描述

3为何需要索引

查多改少的情况

引入索引是为了提高查询数据的效率,但是会拖慢增、删、改的效率

创建索引也需要时间和空间的开销

-- 例:索引和原数据表的关系,就相当于书的目录和书本内容之间的关系

-- 根据书本的目录去查找特定章节的特定内容,远比你拿一本书瞎翻快得多~ ~

涉及到书本内容的修改,现在还需要改目录

案例

1.创建一个表test_user,存放着800w条用户信息

-- 创建用户表

DROP TABLE IF EXISTS test_user;

CREATE TABLE test_user (

    id_number INT,

    name VARCHAR(20) comment '姓名',

    age INT comment '年龄',

    create_time timestamp comment '创建日期'

);

sql语句:(复制运行即可)

-- 构建一个8000000条记录的数据
-- 构建的海量表数据需要有差异性,所以使用存储过程来创建, 拷贝下面代码就可以了,暂时不用理解

-- 产生名字
set global log_bin_trust_function_creators=TRUE;
drop function if exists rand_name;
delimiter $$
create function rand_name(n INT, l INT)
returns varchar(255)
begin 
 declare return_str varchar(255) default '';
 declare i int default 0;
 while i < n do 
	 if i=0 then
			set return_str = rand_string(l);
	 else
		 set return_str =concat(return_str,concat(' ', rand_string(l)));
	 end if;
	 set i = i + 1;
	 end while;
	return return_str;
	end $$
delimiter ;

-- 产生随机字符串
drop function if exists rand_string;
delimiter $$
create function rand_string(n INT)
returns varchar(255)
begin 
 declare lower_str varchar(100) default
	 'abcdefghijklmnopqrstuvwxyz';
 declare upper_str varchar(100) default
	 'ABCDEFJHIJKLMNOPQRSTUVWXYZ';
 declare return_str varchar(255) default '';
 declare i int default 0;
 declare tmp int default 5+rand_num(n);
 while i < tmp do 
	 if i=0 then
			set return_str =concat(return_str,substring(upper_str,floor(1+rand()*26),1));
	 else
		 set return_str =concat(return_str,substring(lower_str,floor(1+rand()*26),1));
	 end if;
	 
	 set i = i + 1;
	 end while;
	return return_str;
	end $$
delimiter ;

-- 产生随机数字
drop function if exists rand_num;
delimiter $$
create function rand_num(n int)
returns int(5)
begin 
 declare i int default 0;
 set i = floor(rand()*n);
return i;
end $$
delimiter ;

-- 向用户表批量添加数据
drop procedure if exists insert_user;
delimiter $$
create procedure insert_user(in start int(10),in max_num int(10))
begin
declare i int default 0; 
 set autocommit = 0;  
 repeat
	set i = i + 1;
	insert into test_user values ((start+i) ,rand_name(2, 5),rand_num(120),CURRENT_TIMESTAMP);
	until i = max_num
 end repeat;
 commit;
end $$
delimiter ;

-- 执行存储过程,添加8000000条用户记录
call insert_user(1, 8000000);

800万条数据,足足运行15min O。o ?
请添加图片描述

2.查询某个人基本信息,id_number = 556677

desc test_user;
+-------------+-------------+------+-----+---------+-------+
| Field       | Type        | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| id_number   | int         | YES  |     | NULL    |       |
| name        | varchar(20) | YES  |     | NULL    |       |
| age         | int         | YES  |     | NULL    |       |
| create_time | timestamp   | YES  |     | NULL    |       |
+-------------+-------------+------+-----+---------+-------+
Key这一列没有东西,说明没有设置索引

千万不能select * from test_user;!!!800w条数据,电脑要炸

select name,age from test_user where id_number = 556677;
-- 全表扫描,在800w条记录上查询id_number为556677的信息
-- 一行行扫描,直到找到id = 556677的为止
+-----------------+------+
| name            | age  |
+-----------------+------+
| Qpala Ejiovjjri |   75 |
+-----------------+------+
1 row in set (4.11 sec)
因为数据量庞大,花了4s才找到这条数据

3.分析

explain sql语句;

MySQL的引擎会分析这个sql语句可能会用到的索引等信息,包括扫描的行数等等

explain select name,age from test_user where id_number = 556677;

请添加图片描述

Key这一列为NULL,说明就是id_number属性没有设置索引

rows这一列显示为7789744,说明可能扫描的行数为700多w条

4设置索引

应该为经常查询的属性设置索引

(查多改少的情况,提高查找效率)

创建索引需要时间和空间的开销

1.创建索引的语句

对于非主键、非唯一约束、非外键的字段,可以创建普通索引

create index 索引名称 on 表名(属性名);

2.在test_user表中为id_number属性创建索引 id_inx

create index id_idx on test_user(id_number);

请添加图片描述

创建一个索引就花时间12.9s,索引创建是需要时间的

3.创建索引之后,再查询,看看能快多少

select name,age from test_user where id_number = 556677;

+-----------------+------+
| name            | age  |
+-----------------+------+
| Qpala Ejiovjjri |   75 |
+-----------------+------+
1 row in set (0.00 sec)

假如每个查询优化4s

假设一个中等规模的网站日活10w,每个用户每天的平均查询操作10次

每天查询100w次,每个查询优化4s

一共优化:100w*4s = 400ws = 1111h = 46天

优化了这么多时间,真的相当恐怖!四十多天

这只是一个普通的索引优化

4.explain 再分析一下

explain select name,age from test_user where id_number = 556677;

请添加图片描述

发现,在很少的常数时间内就可以查询到数据

而且可能扫描的行数也只有一行

@不普通的索引有哪些?

主键约束 => 主键索引

外键约束 => 外键索引

唯一约束 => 唯一键索引

他们三个都是索引

5查看、删除索引

show index from 表名;
查看这个表中有哪些索引


索引的数据结构是BTREE
即B+drop index 索引名称 on 表名;
从表中删除指定索引

6索引背后的数据结构

我们都知道,高效查找数据的数据结构有:

BST二分搜索树 => RBTree,查找的时间复杂度为logN。当数据量非常大时,由于二叉树每个节点最多有两个子树,RBTree的高度很高,数据库的数据都在磁盘上存储,每当访问一个二叉树的节点都得读写一次磁盘,这样就非常慢。

请添加图片描述

(磁盘)普通机械硬盘的读写速度大约几百M/s

内存的读写速度大约是几百G/s

而CPU的运行速度大概又是内存的1000倍

当一个程序有大量的磁盘读写操作,文件IO,这个程序效率是非常低的。

如果使用磁盘进行存储,会导致CPU一直在等待磁盘的读写,导致效率很低。

哈希表:理论上O(1)找到数据,常数时间。但是哈希表无法处理范围查询操作

哈希表是查找数据是否等于指定数据,区间查找他就不行了~~

between I and r

B-树

因此在MySQL的索引上基于B+树的设计(N叉搜索树)

引入N叉搜索树后可以大大降低树的高度(相较于BST来说)

首先了解B-树

B-树,又叫N叉搜索树,即

请添加图片描述

B-树的特点

1.每个树节点上都有多个值

2.每个节点上的(分叉树)子树的个数就是当前节点值的个数 + 1

当前树的节点有3个值,就有4个分叉,即4个子树

3.保证子树中的节点值一定要处在父节点的范围之内

请添加图片描述

查询48:先查询在<50,[50,100],[100,150],>150的哪个范围内,发现在<50范围内,继续向下找,发现又在>45范围内,找到了~ ~

其实B-树中的每个值其实是一个复合值

以学生表(id, name, class_id)为例

以id创建索引id_idx

假如在某个节点中保存了某个学生的id_idx = 100,那么这个节点不止存储了这一个数据,同时也会存储他的name和class_id(晓明,3)

聚簇索引和非聚簇索引

聚簇索引(主键索引,一个表只有一个聚簇索引)

构建聚簇索引树上的每个节点时,需要保存索引列的信息,还需要保存这条记录的完整内容。

非聚簇索引(普通索引,唯一索引,index创建的都是非聚簇索引,一张表中可以有多个非聚簇索引)

构建非聚簇索引树上的每个节点时,除了保存索引列的信息之外,还需要保存该记录的行号(对应的主键id)

请添加图片描述

聚簇索引:查询速度快,一个表只有一个聚簇索引,保存的信息多,占用空间大;

非聚簇索引:查询速度慢,只能找到主键信息,需要回表查询,一个表可以有多个非聚簇索引,保存的信息少,占用空间小。

B+树

请添加图片描述

B+树和B-树最大的区别就是:

每个子节点的最大值都是当前父节点的值。
请添加图片描述

为什么右边没有数据和节点呢?

其实B-树家族是严格平衡树,左右子树的高度差为0,左树和右树的高度完全相等。

怎么考?数据库索引的底层数据结构?

请给我纸和笔,我来作图B+树的结构

四、事务

1.什么是事务

一个事务是一个完整的业务逻辑单元,不可再分。

事务的应用场景 - 银行转账的场景,从A账户向B账户转账1w,至少需要执行两条语句:

update t_act set balance = balance - 10000 where actno = 'A';
update t_act set balance = balabce + 10000 where actno = 'B';
-- 如果在实际生活中,A账户扣款成功但是B账户没有收到钱,则是灾难性的错误!!

-- 因此,这两条语句必须同时成功或者同时失败,不允许一条成功、一条失败。
-- 想要保证这样的效果,就需要数据库的事务机制。

所谓的事务:把若干个SQL操作打包为一个整体,实际执行的时候,这个整体要么全部执行,要么都不执行。

若执行的过程中出现了突发情况,某些操作执行不下去了,MySQL可以保证突发情况恢复之后,数据没有遭受破坏。

=> 通过事务的“回滚” - roll back操作进行数据的还原~~(MySQL中的binlog文件实现,记录了所有表数据的修改动作)

2.事务的四大特性

事务的ACID(原子性、持久性、隔离性、一致性)特性

原子性:(事务中最核心的操作)

一个事务中的所有操作,要么全部执行成功,要么全部执行失败。

(执行失败之后,数据的恢复就通过rollback回滚)


持久性:一个事务执行完成之后,这个事务对数据库的所有修改都是永久的(持久化,保存到磁盘上),不会丢失


一致性:一个事务执行前后的数据都是一种合法性的状态。

事务永远都是从一个一致性状态到另一个一致性状态

在执行事务前后,数据库的数据都是合理的~~

假设执行更新操作之前,B账户余额1,A账户余额500w

没有事务,就有可能出现,B账户余额1,A账户余额499w => 不合理的状态

不管怎么操作,这两个账户余额总和应该是500w零一块,才是合理的


隔离性:多个并发事务访问数据库时,事务之间是相互隔离的,一个事务不应该被其他事务干扰,不同事务之间相互隔离。

普通SQL:一个SQL语句执行的操作,MySQL自身可以保证数据并发时的正确性(通过读写锁)。

事务:多个SQL语句执行的操作,并发执行就会存在相应的问题。

ps.并发与并行

-- 并发:多个任务不一定是在同时执行的,也不一定就是在不同的CPU上执行,单核处理器上的任务调度都属于并发执行。

在QQ中给鹏哥发个爱心的表情 - 任务1

给鹏哥把信息发出去了 a

鹏哥给我回了个信息“恋爱中” b

在微信中问我媳妇还需要干啥家务 - 任务2

我把信息发出去了 c

我媳妇给我回了个微信“把碗洗了,然后把地拖了,再把娃的衣服洗了,你就能去看书了” d

每一个任务有两个子任务,实际上执行顺序为acbd,但是用户却觉得这两个任务是同时发生的,其实在不同时间段执行了不同的任务。并发,即在某一时间段内同时进行,有先后顺序。

-- 并行:多个任务一定是在不同的CPU上同时执行

并行,即在同一时间同时发生。

问题

当鹏哥和铭哥同时操作同一个数据库和数据表可能引发的问题

(模拟多个并发事务访问数据库时,可能存在的问题)

问题1:脏读

事务A在修改数据,事务B读取到了事务A修改后的数据。接着事务A进行了“回滚”,此时事务A前面的修改不作数了~~

此时事务B读到的数据是修改后的数据,就是“脏”数据~~这种情况称为脏读。

问题二:不可重复读

同一个事务在多次相同查询后得到的数据不同。

在不同的查询时,其他事务的修改对于本事务来说是可见的。

-- 事务A: 

select name from stu; 

-- 其他操作

select name from stu;

结果不同了!

事务的三个操作

开启事务

start transaction;
-- 后面的多个sql语句是一个整体!!

START TRANSACTION 立即启动一个事务,而不管当前的提交模式设置如何。 无论当前的提交模式设置如何,以 START transaction 开始的事务必须通过发出显式 COMMIT 或 ROLLBACK 来结束。

回滚操作

rollback;
-- rollback回滚了上次对数据库的修改(即回滚了此次事务的所有操作)

提交事务

commit;
-- 把开启事务之后的所有sql语句统一在数据库上进行持久化(回滚也没用,不会撤销)

在commit之前,事务中所有的操作都是临时的。只有提交之后的事务,才把这些数据真正写入磁盘,对于其他事务也可见这个数据。

3.MySQL事务的四种隔离级别

级别

1.读未提交:处在该隔离界别的事务可以看到其他还没提交的事务,对数据库数据的修改~~ RU(Read Uncommitted)

脏读、不可重复读、环读都有可能出现

2.读已提交:处在该隔离级别的事务可以看到其他已经提交的事务,对数据库的修改~~ RC(Read Committed)

3.可重复读InnoDB引擎默认的隔离级别(Repeatable Read)

一个事务一旦开启,在该隔离级别下,该事务提交之前,多次查询看到的结果是相同的~~

无论其他事务如何修改数据库,在当前这个事务下都是不可见的~~

4.串行化:(Serializable)事务最高隔离级别,所有事务都串行访问数据库,不会发生冲突,不会产生任何错误~~就没有并发了,并发度为0

举例

请添加图片描述

演示

演示一下在MySQL数据库中,可重复读这一隔离级别下的情况:

1.打开两个shell终端,开启两个事务

请添加图片描述

2.在左边的事务中执行插入语句,可以看到右边事务读到的还是之前的数据

请添加图片描述

3.将左边的事务提交,右边的事务继续读test表,结果还是相同的

请添加图片描述

这就是MySQL5.5之后,支持事务的版本,使用InnoDB引擎的存储结构,默认的事务隔离级别

可重复读(Repeatable Read) RR

只要本事务没有提交,查询的所有值保证都是相同的,和其他事务隔离,其他事务的修改对于本事务是不可见的~~

4.在左边的事务中插入id为3的行

ps:此时左边的事务(暂称为事务x),已经提交了,也就是在磁盘上永久进行持久化存储了。

但是,此时右边的事务(暂称为事务y)并没有提交,以事务y的视角,并不明白这一点。

那么可以在事务y中,继续添加id=3的数据吗?

当然不可以!因为在磁盘中已经实实在在的有那个数据了
请添加图片描述

5.将事务y提交,并查询

请添加图片描述

幻读:

事务y查询id为3的行,查询不到,插入又不成功,(3,‘liu’,1)这条数据就像 幻觉 一样出现。这就是所谓的“幻读”

事务中,注意:

四种隔离级别

脏读

不可重复读

幻读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/418112.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux项目日志管理log4cpp的安装与使用【结合sample】

文章目录前言log4cpp安装log4cpp的使用设置类别输出的&#xff08;category&#xff09;和日志优先级&#xff08;priority&#xff09;定义一个宏用于输出日志配置文件使用log4cpp的栗子结语前言 我们都清楚对于一个项目来说它的日志信息是非常重要的&#xff0c;那么我们应该…

springcloud微服务架构搭建过程

项目地址&#xff1a;源代码 仅作为学习用例使用&#xff0c;是我开发过程中的总结、实际的一部分使用方式 开发环境&#xff1a; jdk11 springboot2.7.6 springcloud2021.0.5 alibabacloud 2021.0.4.0 redis6.0 mysql8.0 一、项目搭建 wdz-api&#xff1a;存放远程服务调用相关…

VS for Qt 向MySql 数据库中插入中文

问题&#xff1a; 今天我想向数据库中插入中文&#xff0c;但是&#xff0c;插入的时候会报错&#xff1a; 首先先看报错&#xff1a; QSqlError("1054", "QMYSQL: Unable to execute query", "Unknown column 韩红 in field list")如果错误码…

将Linux服务器上的项目上传至Github

使用git上传项目到github常规的步骤继续上传注意事项参考文章常规的步骤 初始化git空间 git init向缓冲区添加想要上传的文件 git add -f /data/xuhongbo/xuhongbo.code/unbiased_sgg_xuhongbo_BCL/maskrcnn_benchmark/*添加备注信息告诉机器&#xff0c;你真的要添加上述文…

elasticsearch-7.17.9

1、ElasticSearch 1.1、概念 1.1.1、分片(shard) 1、分片 在ES中所有数据的文件块&#xff0c;也是数据的最小单元块&#xff0c;整个ES集群的核心就是对所有分片的分布、索引、负载、路由等达到惊人的速度。 实列场景&#xff1a; 假设 IndexA 有2个分片&#xff0c;向 I…

数据结构 - 计数排序 | C

什么是计数排序 如上图&#xff0c;统计数组中值的个数&#xff1a; 2个[1]&#xff1a;1&#xff0c;1 1个[2]&#xff1a;2 3个[3]&#xff1a;3&#xff0c;3&#xff0c;3 2个[4]&#xff1a;4&#xff0c;4 传给原数组&#xff1a;&#xff08;即完成排序↓&#xff09; …

Fast R-CNN

目录 1. 关于 R-CNN 的缺点 2. Fast R-CNN 3. Fast R-CNN 算法的流程 3.1 CNN 特征提取 3.2 ROI pooling 3.3 Fast R-CNN 的输出 3.4 损失函数 4. Fast R-CNN的不足 1. 关于 R-CNN 的缺点 RCNN算法流程如下 RCNN算法分为四个步骤&#xff1a; SS 算法生成2000个候选框…

解除游戏多开限制,关闭互斥体句柄

游戏限制多开有很多种方法 比如说遍历窗口,遍历进程,配置文件,注册表,互斥体,mac地址,ip,公共文件,内存映射等等.方法很多.但是绝大部分游戏限制多开都是采用的互斥体.这节课我们来讲解一下关闭互斥体句柄来实现多开.例子为CQYH(这里的防护建议是,增加多种多开限制的方法 以及 …

系统安全与应用【上】

文章目录1.账号安全控制1.1 系统账号清理1.2 密码安全控制1.3 命令历史限制1.4 终端自动注销2.系统引导和登录控制2.1 使用su命令切换用户2.2 限制使用su命令的用户3.可插拔式认证模块PAM3.1 linux中的PAM安全认证3.2 PAM认证原理3.3 PAM认证的构成3.4 PAM安全认证流程3.5 使用…

(八)【软件设计师】计算机系统—浮点数

浮点数 浮点数。当机器字长为n时&#xff0c;定点数的补码和移码可表示2的n方个数&#xff0c;而其原码和反码只能表示2"-1个数&#xff08;0的表示占用了两个编码)&#xff0c;因此&#xff0c;定点数所能表示的数值范围比较小&#xff0c;在运算中很容易因结果超出范围而…

实力爆表,日日新成为AI领航者

目录正式发布自建算力SenseChat编程能力图像生成后言上周五&#xff0c;阿里发布大模型通义千问&#xff0c;正式开始邀请内测。本周一&#xff0c;人工智能巨头商汤科技正式发布“日日新”大模型体系&#xff0c;全面丰富的产品体系&#xff0c;多个功能表现超预期&#xff0c…

MobTech MobPush|不同手机厂商推送问题

配置了华为厂商推送&#xff0c;为什么有的华为设备无法接收离线消息 首先&#xff0c;排查配置的华为厂商参数是否正确&#xff1b; 其次&#xff0c;检查华为设备EMUI版本&#xff0c;低于5.0可能不支持&#xff0c;如果低于5.0&#xff0c;可以尝试升级设备里的‘华为移动服…

Google代码覆盖率最佳实践

软件质量保障: 所寫即所思&#xff5c;一个阿里质量人对测试的所感所悟。谷歌一直倡导的领域之一是使用代码覆盖率数据评估风险并识别测试中的真空。然而&#xff0c;代码覆盖率的价值一直是个争议的话题。每次聊到代码覆盖率时&#xff0c;似乎都会引发无尽的争论。由于大家固…

微信小程序开发 | 小程序开发框架

小程序开发框架7.1 小程序模块化开发7.1.1 模块7.1.2 模板7.1.3 自定义组件7.1.4插件7.2 小程序基础样式库—WeUI7.2.1 初识WeUI7.2.2【案例】电影信息展示7.3 使用vue.js开发小程序7.3.1 初识mpvue7.3.2 开发工具7.3.3 项目结构7.3.4【案例】计数器7.4 小程序组件化开发框架7.…

Ztree树状的处理

1.用一个div进行包裹ztree结构&#xff0c;引用相关的js代码和css样式&#xff0c;这里用的样式是awesome.css 所引用的js文件&#xff0c;css文件可以在网上下载&#xff08;这里所用到的jquery-ztree文件放在网盘了&#xff09; <ul id"tree" class"ztre…

企业即时通讯软件开发基本功能有哪些?

即时通讯是基于互联网技术的新型交流沟通方式&#xff0c;是目前最流行的通讯方式&#xff0c;广泛的应用市场使得各种各样的即时通讯软件系统也层出不穷&#xff0c;企业即时通讯就是其中的一种延伸。是一种面向企业终端使用者的网络营销、网络沟通和内容管理的工具服务&#…

mysql基础安装以及问题

mysql 基础安装以及问题安装MySQL8.0的安装&#xff1a;MySQL5.7 版本的安装、配置卸载服务的启动与停止图形化工具推荐安装 官网&#xff1a;https://www.mysql.com MySQL8.0的安装&#xff1a; 这里是写你直接要安装的目录&#xff1a; 之后配置mysql8.0 注意&#x…

不会注册ChatGPT?4个国内网站让你尽情体验

最近火出圈的科技新词非“ChatGPT”莫属了。 但是由于ChatGPT注册起来比较困难&#xff0c;我到现在都还学不会如何注册.... 但是&#xff01;世上无难事&#xff01;只要有心人&#xff01; 我千辛万苦终于找到几个ChatGPT平替的网站了。 AI中文智能对话 地址&#xff1a;…

目标检测入门:发展历史

预备知识 分类classification 输出:物体的类别 评估方法:准确率 定位location 输出:方框在图片中的位置(x,y,w,h) 评估方法:交并比IOU 定位的解决思路: 思路一:看做回归问题 看做回归问题,我们需要预测出(x,y,w,h)四个参数的值,从而得出方框的位置 成为class…

数字证书的相关专业名词(下)---OCSP及其java中的应用

一、前言 上篇文章我们了解了根证书和校验证书有效性中的一个比较重要的渠道–CRL&#xff0c;但是CRL有着时间延迟&#xff0c;网络带宽消耗等缺点&#xff0c;本篇文章我们了解另一种更高效也是目前被广泛应用的校验证书有效性的另一种方式–OCSP&#xff0c;并且我会结合ja…