当前位置: 首页 > news >正文

【MySQL|第八篇】事务与索引

八、数据库事务

1、概述:

        事务(Transaction),是由一系列对数据库表中数据,进行访问与更新的操作,所组成的一个执行逻辑单元

        只有DML语句才会产生事务,其他语句不会产生事务

        DML语句执行的时候,如果当前有事务,那么就使用这个事务。如果当前没有事务,则产生一个新事务

        commit、rollbackDDL语句都可以把当前事务给结束掉

        commit和DDL语句结束事务的方式是把这个事务给提交了,然后DML操作永久生效

        rollback结束事务的方式是把这个事务给回滚了,默认回滚到事务开始的状态

        mysql默认是开启事务,即 autocommit = 1,自动提交事务。即执行insert、updatedelete操作,立刻提交。

MySQL事务的生命周期包括以下几个阶段:

1. 开始(BEGIN):事务的生命周期始于BEGIN语句的执行。在开始阶段,MySQL会为该事务分配一个唯一的事务ID,并开始记录事务日志。

2. 执行(执行SQL语句):在事务开始后,可以执行多个SQL语句,包括插入(INSERT)、更新(UPDATE)、删除(DELETE)等操作。这些操作会在事务日志中进行记录,但并不会立即影响数据库的实际数据。

3. 提交(COMMIT):当所有SQL语句执行完毕后,可以选择提交事务。提交操作会将事务中的所有修改永久保存到数据库中,并释放相关的锁资源。

4. 回滚(ROLLBACK):在事务执行过程中,如果发生错误或需要取消之前的修改,可以选择回滚事务。回滚操作会撤销事务中的所有修改,恢复到事务开始前的状态。

5. 结束(END):事务的生命周期在提交或回滚后结束。结束阶段会释放所有与该事务相关的资源,并关闭事务日志。

        需要注意的是,MySQL默认使用自动提交模式(autocommit),即每个SQL语句都被视为一个单独的事务,会自动执行提交操作。如果需要使用显式事务控制,可以使用BEGINCOMMITROLLBACK语句来手动管理事务的生命周期。

2、事务特征:

数据库事务必须具备ACID特性Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。

  • 原子性(Atomicity

一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

如:张三转账给李四钱,转账过程中停电了,应该转账不生效(回退), 事务的原子性

  • 一致性(Consistency

事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。

如:张三转账给李四钱,转帐之前和转账之后,账务总额应该保持不变。

  • 隔离性(Isolation

指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。

如:张三转账过程,李四看不到张三账户的变化

  • 持久性(Durability

指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

如:如果转到错误的人的账户上,钱是退不回来的,事务一旦完成,事务中所涉及的数据,不能再被此次事务所更改。

3、提交回滚:

(1)查看事务:

        mysql默认是开启事务,即 autocommit = 1,自动提交事务。即执行 insert update delete 操作,立刻提交。

select @@autocommit;

(2)开启事务:

        在MySQL命令行的默认设置下,事务都是自动提交的,即执行SQL语句后就会马上执行COMMIT操作。

        因此要显式的开启一个事务须使用命令 BEGIN START TRANSACTION ,或者执行命令 SET AUTOCOMMIT=0 ,用来禁止使用当前会话的自动提交。

语法:

-- 开启1个事务begin;-- 也可以使用start transaction;-- 也可以使用,关闭事务自动提交,改为手动提交SET AUTOCOMMIT=0;

(3)事务提交:

开启事务以后,执行DML语句遇到commit关键字或DDL语句,会提交事务。

例如:

-- 开启事务手动提交SET AUTOCOMMIT=0;insert ... 第一次执行DML语句,新建事务(用A标识)update ... 这个操作是事务A中的操作insert .. 这个操作是事务A中的操作commit; 让事务A里面的三个操作生效、事务A结束delete ... 此时没有事务,执行新的DML语句会产生新事务(用B标识)insert .. 这个操作是事务B中的操作insert .. 这个操作是事务B中的操作rename .. 遇到DDL语句,事务自动提交insert .. 此时没有事务,执行新DML会创建新事务(用C标识)...

注意:有一些语句会使得事务结束

  • DDL语句,ALTER DATABASEALTER EVENTALTER PROCEDUREALTER TABLEALTER VIEWCREATE TABLEDROP TABLERENAME TABLETRUNCATE TABLE等;
  • 修改MYSQL架构的语句,CREATE USERDROP USERGRANTRENAME USERREVOKESET PASSWORD
  • 管理语句,ANALYZE TABLECACHE INDEXCHECK TABLELOAD INDEX INTO CACHEOPTIMIZE TABLEREPAIR TABLE等。

测试用表:

-- 新建测试表create table t_customer(id int,name varchar(20) not null,primary key(id));-- 测试完成可以删除表drop table t_customer;

例如,

-- 开启事务begin;insert into t_customer(id,name) values(1,'tom');insert into t_customer(id,name) values(2,'jack');insert into t_customer(id,name) values(3,'rose');update t_customer set name='lucy' where id=1;commit;-- 开启事务begin;delete from t_customer where id=3;update t_customer set name='lily' where id=2;select * from t_customer;-- DDL语句,会自动提交事务alter table user3 add phone varchar(20);select * from t_customer;

(4)事务回滚:

在进行事务回滚的时候,默认是回滚到事务开始时候的状态

同时,在事务中,我们也可以设置多个回滚点,让事务回滚到指定的位置。

例如,使用关键字 savepoint ,用来设置回滚点

DML语句1

savepoint A

DML语句2

savepoint B

DML语句3

rollback to A/B

rollback

注意事项:rollback to 回滚点,此时事务并没结束。这个时候还可以接着rollback回滚或者commit提交,使事务结束。

案例:

create table t_user(id int primary key,name varchar(100),salary int);-- 开启事务start transaction;insert into t_user values(1,'tom',1000);savepoint A;insert into t_user(id,name) values(2,'zs');savepoint B;delete from t_user;-- 回滚到Brollback to B;select * from t_user;-- 回滚事务(生效)rollback;select * from t_user;-- 测试完成后可以删除表drop table t_user;查询结果:select * from t_user;

4、隔离级别:

MySQL支持多用户并发访问,并且保证多个用户同时访问相同的数据时不会造成数据的不一致性。当多个用户同时访问相同的数据时,如果不进行任何隔离控制,可能导致以下问题:

  • 脏读

        会话1读到会话2未提交的数据

  • 不可重复读

        在同一事务中,两次读取同一数据,得到内容不同。

  • 幻读

        同一事务中,用同样的操作读取两次,得到的记录数不相同。

为了处理上述问题,SQL标准定义了4类隔离级别,具体如下图:

案例展示:

案例1:查看当前数据库中的默认隔离级别

show variables like '%isolation%';

案例2:修改数据库中的隔离级别

set session transaction isolation level READ COMMITTED;

注意事项:上述修改只在当前会话中生效,想要永久生效可以修改mysql配置文件

-- 恢复成默认隔离级别

set session transaction isolation level REPEATABLE READ;

案例展示:

开启两个终端,使用相同用户登录,将隔离级别设置成 读已提交,然后进行

测试。

开启终端1,准备工作如下:

-- 设置为 读已提交
set session transaction isolation level READ COMMITTED;
-- 删除表
drop table if exists t_account;
-- 创建账户表并插入数据
create table t_account(id int(11) primary key auto_increment,name varchar(20) not null,balance decimal(10,2) default 0
);
insert into t_account(name,balance) values('zs',2000.5),('ls',3020.5);
-- 查询账户信息
select * from t_account;

测试正式开始(终端1):

-- 1.开启事务1
begin;
-- 5.查询账户信息
select * from t_account;
-- 7.查询账户信息
select * from t_account;
-- 注意观察两次select查询结果是否相同(结果不同,说明产生了不可重复读)
-- 9.查询账户信息
select * from t_account;
-- 11.查询账户信息
select * from t_account;
-- 注意观察两次select查询结果是否相同(结果不同,说明产生了幻读)
-- 12.提交事务
commit;

终端2测试:

-- -- 开启终端2,准备工作如下
-- 设置为 读已提交
set session transaction isolation level READ COMMITTED;
-- 2.查询账户信息
select * from t_account;
-- 3.开启事务2
begin;
-- 不可重复读测试:两次select结果不同
-- 4.更新数据
update t_account set balance=1000.5 where id=1;
-- 6.提交事务
commit;
-- 幻读测试:两次select得到的记录数不同
-- 8.先开启事务,再删除数据
begin;
delete from t_account where id=2;
-- 10.提交事务
commit;

注意:最后恢复默认隔离级别

set session transaction isolation level REPEATABLE READ;

九、索引:

        在 MySQL 中,索引(Index)是一种数据结构,用于提高数据库表的查询性能。索引可以加速数据的检索,减少查询所需的时间和资源消耗。

        索引用于快速定位和访问表中的数据。它类似于书籍的目录,可以根据关键字快速找到对应的数据行,而无需全表扫描。

索引优缺点:

优点:加快数据检索速度,提高查找效率

缺点:占用数据库物理存储空间,当对表中数据更新时,索引需要动态维护,降低数据写入效率

创建原则:

  • where order by 涉及的列上尽量建立索引
  • 更新频繁的列不应设置索引
  • 数据量小的表不要使用索引
  • 重复数据多的字段不应设为索引(如性别,只有男和女),重复数据超15%就不该建索引

1、存储索引:

        在 MySQL 中,存储引擎(Storage Engine)是负责处理数据的存储和检索的模MySQL 支持多种存储引擎,不同的存储引擎可以在不同的应用场景中提供不同的优势和特性。

        MySQL 数据库存储引擎,定义了数据如何存储、如何索引以及如何处理查询。

常见存储引擎:

1. InnoDBInnoDB MySQL 5.5 版本之后的默认存储引擎它提供了事务支持、行级锁定、外键约束和崩溃恢复等功能。 InnoDB 引擎适用于需要事务支持和高并发读写操作的应用场景。

2. MyISAMMyISAM MySQL 5.5 版本之前的默认存储引擎它以其简单和高性能而闻名,适用于大量的读操作和只读数据。MyISAM 引擎不支持事务和行级锁定。

3. Memory:或称为 Heap存储引擎,将数据存储在内存中,提供了非常快速的读写性能

但是,由于数据存储在内存中,重启服务器或断电会导致数据丢失。 Memory 引擎适用于临时数据存储和高速缓存等场景。

2、底层实现:

MySQL 8 默认存储引擎为InnoDB ,其采用B+Tree作为索引常用底层数据结构。

其他数据结构介绍:

1Hash

        如果基于哈希表实现索引,则对于每一行数据,存储引擎会对索引列计算得到一个唯一的哈希码(hash code)。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。

弊端:通过hash值定位数据非常快,但只有精确匹配索引所有列的查询才有效!

因为散列表中的值是无序的,无法进行大小的比较。

MySQL中,常见存储引擎并不支持 Hash 索引,只有Memory引擎显式支持哈希索引。这也是Memory引擎表的默认索引类型,Memory引擎同时也支持B-Tree索引。

2)二叉树

        二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点,都满足其左子树上所有结点的数据域均小于或等于根结点的数据域,右子树上所有结点的数据域均大于根结点的数据域。

使用二叉树可以提高查询数据的速度,但是有可能产生不平衡类似于链表的结,如下图右侧:

3)平衡二叉树

        平衡二叉树是采用二分法思维把数据按规则组装成一个树形结构的数据,用这个树形结构的数据减少无关数据的检索,大大的提升了数据检索的速度,其特点:

  • 它的左子树和右子树都是平衡二叉树
  • 左子树比中间小,右子树比中间值
  • 左子树和右子树的深度之差的绝对值不超过1

弊端:

  • 平衡二叉树只有2个节点,如果数据太多,树的深度加大,检索效率变低
  • 插入操作需要旋转,需要额外耗费时间
  • 它支持范围查询,但回旋查询的效率比较低

比如上图中要查找大于8的数据,需要回旋到父节点710。如果存放百万条数据的情况下,树高度越高,查询效率会越

4BTree

B-Tree可以有效的解决之前的数据结构中存在的问题。

B树是多叉树,每个节点中可以存储多个数据,且每个节点中数据是有序的,树的高度值更小,查询效果更高。

补充内容:B树的阶(Order)是指B树节点中最大子节点数量。具体来说,对于一个B树节点,它最多可以包含(阶-1)个关键字(Keys)和(阶)个子节点(Children)。

B-Tree弊端:

  • 范围查找效率不高,比如查询 [2039]
  • 查询效率不稳定:离根节点近则查询快,远则慢
  • 树高度还有下降空间

5B+Tree

MyISAM引擎

MyISAM引擎使用B-Tree作为索引结构,叶节点的data域存放的是数据行的地址

InnoDB引擎

InnoDB引擎使用B+Tree作为索引结构,叶子节点的data域存放的是行数据,相比MyISAM效率要高一些,但是占硬盘内存更多

3、索引分类:

按照功能划分,索引划为以下分类:

1. 单列索引

        普通索取

        主键索引

        唯一索引

2. 组合索取

3. 全文索取

4. 空间索引(了解)

5. 其他索引(了解)

4、单列索引:

普通索引

语法:

CREATE TABLE [IF NOT EXISTS] tb_name [(

字段1 数据类型 [约束条件] [默认值] [COMMENT '注解'],

字段2 数据类型 [约束条件] [默认值] [COMMENT '注解'],

字段3 数据类型 [约束条件] [默认值] [COMMENT '注解'],

......

[表约束条件]

index index_name(col_name...)

...

)][engine=innodb] [default charset=utf8];

create index index_name on tb_name(col_name);

alter table tb_name add index index_name(col_name);

案例1:创建教师表,并指定普通索引

create table tea(id int primary key auto_increment,name varchar(20),age int,index index_name(name));

案例2:创建教师表之后在构建索引

create table tea1(id int primary key auto_increment,name varchar(20),age int);create index index_name on tea1(name);

案例3::查看briup数据库中的所有索引

select *
from mysql.innodb_index_stats
where database_name='briup';

案例4:查看briup数据库中教师表中所有索引

show index from tea;

案例5:删除tea表中索引

drop index index_name on tea;


alter table tea drop index index_name;

唯一索引

唯一索引与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。

案例1:创建教师表tea3name为唯一索引

create table tea3(id int primary key auto_increment,name varchar(20),age int,unique index_name(name));

create table tea3(id int primary key auto_increment,name varchar(20),age int);create unique index index_name on tea3(name);

create table tea3(id int primary key auto_increment,name varchar(20),age int
);
alter table tea3 add unique index_name(name);
主键索引

创建表时,MySQL会自动在主键列上建立一个索引,这就是主键索引。主键是具有唯一性并且不允许为NULL

案例1:创建教师表tea4,设置id为主键索引

create table tea4(id int primary key auto_increment,name varchar(20),age int
);

create table tea4(id int,name varchar(20),age int
);
alter table tea4 add primary key(id);

5、组合索引:

组合索引也叫复合索引,指的是我们在建立索引的时候使用多个字段。

例如同时使用身份证和用户编号建立索引,建立的索引可以为普通索引、唯一索引或主键索引。

案例1:创建教师表tea5,设置id和名字为组合索引

create table tea5(id int,name varchar(20),age int,index index_name(id,name));

或:

create table tea5(id int,name varchar(20),age int);create index index_name on tea5(id,name);

create table tea5(id int,name varchar(20),age int);alter table tea5 add index index_name(id,name);

注意事项:复合索引的使用复合最左原则。

1. where id=1 可以使用索引,条件里面必须包含索引前面的字段才能够进行匹配

2. where name='lisi' 不可以使用索引

3. where name='lisi' and id=12 可以使用索引,mysql本身就有一层sql优化,他会根据sql来识别出来该用哪个索引

4. where id=12 and name='lisi' 可以使用,顺序一致

补充内容:

        复合最左原则(Composite Key Leftmost Rule)是在关系型数据库中用于优化查询性能的一种规则。它指出在使用复合索引时,查询条件中的列应该按照索引中列的顺序从左到右进行匹配。遵循复合最左原则可以帮助优化查询性能,提高数据库操作的效率。

        具体来说,复合最左原则要求在查询中使用索引时,应该按照索引定义中列的顺序从左到右依次指定查询条件。如果查询条件中的列不是按照索引定义的顺序进行匹配,数据库引擎可能无法有效地使用索引,从而导致查询性能下降。

        例如,考虑一个复合索引 (col1, col2, col3),按照复合最左原则,以下查询可以有效地使用该索引:

SELECT *

FROM table

WHERE col1 = 'value1' AND col2 = 'value2' AND col3 = 'value3';

而以下查询则无法有效地使用该索引:

SELECT *

FROM table

WHERE col2 = 'value2' AND col1 = 'value1' AND col3 = 'value3';

因为查询条件中的列的顺序与索引定义的顺序不一致,数据库引擎可能无法充分利用索引,导致查询性能下降。


文章转载自:

http://0nZ9VnFM.ydryk.cn
http://frsSYL4g.ydryk.cn
http://XRAvvBir.ydryk.cn
http://ae8nKhLp.ydryk.cn
http://KImqBtle.ydryk.cn
http://wcgfiiH0.ydryk.cn
http://43FBxWAr.ydryk.cn
http://fdtqlpsm.ydryk.cn
http://cQYGjWPa.ydryk.cn
http://q9XBT2VP.ydryk.cn
http://eYrDeheI.ydryk.cn
http://OW9rW8wj.ydryk.cn
http://ydkpQdtI.ydryk.cn
http://47xZUTxf.ydryk.cn
http://pH7jE3wv.ydryk.cn
http://6ZMXZNwf.ydryk.cn
http://bvVflncA.ydryk.cn
http://LvXMKZlb.ydryk.cn
http://UEpaaavT.ydryk.cn
http://vL7kAT7C.ydryk.cn
http://miIDA2av.ydryk.cn
http://E4NpqzNB.ydryk.cn
http://Bou2LU92.ydryk.cn
http://3IDzPe1x.ydryk.cn
http://ew7hdH0u.ydryk.cn
http://xVnHjuOg.ydryk.cn
http://qNcRBScv.ydryk.cn
http://JyiPQYxu.ydryk.cn
http://DDxBzqGf.ydryk.cn
http://Ye4jEBkR.ydryk.cn
http://www.dtcms.com/a/383307.html

相关文章:

  • OD C卷 - 小明找位置
  • JavaScript与jQuery:从入门到面试的完整指南
  • 最长上升子序列(LIS)全解析:从基础到进阶(基础讲解篇)
  • 海盗王64位dx9客户端修改篇之七
  • 【c++进阶系列】:map和set的模拟实现(附模拟实现的源码)
  • Redis的RedLock
  • AutoGen——自定义Agent
  • 第5节-连接表-Natural-Join
  • CentOS Docker 环境下安装 HertzBeat 并配置 VictoriaMetrics 时序数据库指南
  • 【Linux】 存储分级的秘密
  • GitAgent-面壁智能联合清华大学发布的大模型智能体应用框架
  • 《基于国产Linux的机房终端安全重构方案》
  • JavaWeb-Servlet总结及JSP
  • 《黑神话:悟空》Xbox版本性能模式画质分析
  • 支持向量机:从理论到实践
  • 软件体系结构——发展脉络
  • 【C++】队列queue的使用
  • 对网络通信领域的“活化石”与“瑞士军刀”—— `telnet`
  • 迭代器和生成器的区别与联系
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘numpy’ 问题
  • ffplay数据结构分析
  • 我爱学算法之—— 位运算(上)
  • LeetCode 分类刷题:2187. 完成旅途的最少时间
  • Redis持久化之AOF:日志记录的艺术,数据安全保障详解
  • 应急响应-事件处理学习大纲(1)
  • 基于「YOLO目标检测 + 多模态AI分析」的遥感影像目标检测分析系统(vue+flask+数据集+模型训练)
  • 【Android】Viewpager2实现无限轮播图
  • 【前端教程】从基础到优化:一个登录页面的完善过程
  • 一文入门python中的进程、线程和协程
  • Tempus Fugit: 3靶场