MySQL事务、引擎

MySQL事务

事务的概念

  • 事务是一种机制、一个操作序列,包含了一组数据库操作命令==,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行。
  • 事务是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时,事务是最小的控制单元。
  • 事务适用于多用户同时操作的数据库系统的场景,如银行、保险公司及证券交易系统等等。
  • 事务通过事务的整体性以保证数据的一致性
  • 事务能够提高在向表中更新和插入信息期间的可靠性

说白了,所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。

事务的ACID特点

ACID,是指在可靠数据库管理系统(DBMS)中,事务(transaction)应该具有的四个特性:原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability)。这是可靠数据库所应具备的几个特性。

原子性

指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。

  • 事务是一个完整的操作,事务的各元素是不可分的。
  • 事务中的所有元素必须作为一个整体提交或回滚。
  • 如果事务中的任何元素失败,则整个事务将失败。

案例:
A给B转帐100元钱的时候只执行了扣款语句,就提交了,此时如果突然断电,A账号已经发生了扣款,B账号却没收到加款,在生活中就会引起纠纷。这种情况就需要事务的原子性来保证事务要么都执行,要么就都不执行。

一致性

指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。

  • 当事务完成时,数据必须处于一致状态。
  • 在事务开始前,数据库中存储的数据处于一致状态。
  • 在正在进行的事务中,数据可能处于不一致的状态。
  • 当事务成功完成时,数据必须再次回到已知的一致状态。

案例:
对银行转帐事务,不管事务成功还是失败,应该保证事务结束后表中A和B的存款总额跟事务执行前一致。

隔离性

指在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。

  • 对数据进行修改的所有并发事务是彼此隔离的,表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务。
  • 修改数据的事务可在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数据。
  • 也就是说并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的。

持久性

在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
指不管系统是否发生故障,事务处理的结果都是永久的。
一旦事务被提交,事务的效果会被永久地保留在数据库中。

总结:在事务管理中,原子性是基础,隔离性是手段,一致性是目的,持久性是结果。

数据库的隔离

并发访问导致的数据读取问题

  1. 脏读:当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
    在这里插入图片描述

  2. 不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)
    在这里插入图片描述

  3. 幻读:一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,另一个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,操作前一个事务的用户会发现表中还有一个没有修改的数据行,就好象发生了幻觉一样。
    在这里插入图片描述

不可重复读和幻读到底有什么区别呢?

(1) 不可重复读是读取了其他事务更改的数据,针对update操作

解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据。

(2) 幻读是读取了其他事务新增的数据,针对insert和delete操作

解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据。

隔离级别

MySQL事务支持如下四种隔离,用以控制事务所做的修改,并将修改通告至其它并发的事务:

  1. 未提交读(Read Uncommitted(RU)):
    允许脏读,即允许一个事务可以看到其他事务未提交的修改。

  2. 提交读(Read Committed(RC)):
    允许一个事务只能看到其他事务已经提交的修改,未提交的修改是不可见的。防止脏读。

  3. 可重复读(Repeatable Read(RR)):—mysql默认的隔离级别
    确保如果在一个事务中执行两次相同的SELECT语句,都能得到相同的结果,不管其他事务是否提交这些修改。可以防止脏读和不可重复读。

  4. 串行读(Serializable):—相当于锁表
    完全串行化的读,将一个事务与其他事务完全地隔离。每次读都需要获得表级共享锁,读写相互都会阻塞。可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的效率。
    在这里插入图片描述

事务隔离级别配置

  • 全局级:对所有的会话有效
  • 会话级:只对当前的会话有效

MySQL 隔离界别查看

  • 查看回话隔离级别
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
  • 查看系统隔离级别
SELECT @@global.tx_isolation;

MySQL 隔离级别修改

  • MySQL 默认的隔离级别是可重复读( REPEATABLE READ)
  • 在 my.inf 文件中修改隔离级别
transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}

在这里插入图片描述

  • 用户可以用SET TRANSACTION语句改变单个会话或者所有新进连接的隔离级别。语法如下:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

在这里插入图片描述

事务控制语句

  • BEGIN 或 START TRANSACTION:显式地开启一个事务。
  • COMMIT 或 COMMIT WORK:提交事务,并使已对数据库进行的所有修改变为永久性的。
  • ROLLBACK 或 ROLLBACK WORK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。
  • SAVEPOINT H1:使用 SAVEPOINT 允许在事务中创建一个回滚点,一个事务中可以有多个 SAVEPOINT;“H1”代表回滚点名称。
  • ROLLBACK TO [SAVEPOINT] S1:把事务回滚到标记点。
    提前准备一个简单的数据表
create database mydb;
	##创建mydb数据库

use mydb;
	##使用mydb数据库

create table account(id int(10) primary key not null, name varchar(40),money double);
	##创建account数据表

insert into account values(1,'磊磊',1000);
 	##在account数据表添加数据(id=1,name=磊磊,money=1000)
 
insert into account values(2,'岩岩',1000);
	##在account数据表添加数据(id=2,name=岩岩,money=1000)

在这里插入图片描述

测试提交事务

begin;
	##开启一个事务

update account set money= money - 100 where name='磊磊';
	##更新数据表中的数据记录(name=磊磊的行数据money - 100)

commit;
	##提交事务
	
quit
	##退出mysql

在这里插入图片描述

测试回滚事务

begin;
	##开启一个事务
	
update account set money= money + 100 where name='磊磊';
	##更新数据表中的数据记录(name=磊磊的行数据money + 100)

select * from account;
	##查看account表内数据

rollback;
	##回滚

select * from account;
	##查看account表内数据

quit
	##退出mysql
	

在这里插入图片描述

测试多点回滚

begin;
	##开启一个事务
	
update account set money= money + 100 where name='磊磊';
	##更新数据表中的数据记录(name=磊磊的行数据money + 100)
	
savepoint S1;
	##创建一个回滚点S1
	
update account set money= money - 100 where name='岩岩';
	##更新数据表中的数据记录(name=岩岩的行数据money - 100)
	
savepoint S2;
	##创建一个回滚点S2
	
insert into account values(3,'小唐老师',100);
	##在account数据表添加数据(id=3,name=小唐老师,money=100)

###检查

select * from account;
	##查看account表内数据(最新)
	
rollback to S2;
	##把事务回滚到标记点S2
	
select * from account;
	##查看account表内数据(回滚点S2的内容)
	
rollback to S1;
	##把事务回滚到标记点S1
	
select * from account;
	##查看account表内数据(回滚点S1的内容)

在这里插入图片描述
在这里插入图片描述

使用 set 设置控制事务

SET AUTOCOMMIT=0;
	##禁止自动提交
	
SET AUTOCOMMIT=1;
	##开启自动提交,Mysql默认为1
	
SHOW VARIABLES LIKE 'AUTOCOMMIT';
	##查看Mysql中的AUTOCOMMIT值

  • 如果没有开启自动提交,当前会话连接的mysql的所有操作都会当成一个事务直到你输入rollback|commit;当前事务才算结束。当前事务结束前新的mysql连接时无法读取到任何当前会话的操作结果。
  • 如果开起了自动提交,mysql会把每个sql语句当成一个事务,然后自动的commit。
  • 当然无论开启与否,begin; commit|rollback; 都是独立的事务。
例:关闭自动提交事务
use mydb;
	##使用mydb数据库
	
select * from account;
	##查看account表内数据

SET AUTOCOMMIT=0;
	##禁止自动提交
	
update account set money= money + 100 where name='岩岩';
	##更新数据表中的数据记录(name=岩岩的行数据money + 100)

select * from account;
	##查看account表内数据

quit
	##退出mysql

mysql -u root -p
	##登录MySQL、
	
use mydb;
	##使用mydb数据库

select * from account;
	##查看account表内数据

在这里插入图片描述
在这里插入图片描述

死锁

是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象,若无外力作用,事务都将无法继续运行。此时称系统处于死锁状态或系统产生了死锁。

例如,如果事务A锁住了记录1并等待记录2,而事务B锁住了记录2并等待记录1,这样两个事务就发生了死锁现象。计算机系统中,如果系统的资源分配策略不当,更常见的可能是程序员写的程序有错误等,则会导致进程因竞争资源不当而产生死锁的现象。

如何避免死锁?

  1. 设置事务的锁等待超时时间 innodb_lock_wait_timeout
  2. 设置开启死锁检测功能 innodb_deadlock_detect
  3. 为表建立合理的索引,减少表锁发生的概率
  4. 如果业务允许,可以降低隔离级别,比如选用 提交读 Read Committed 隔离级别,从而避免间隙锁导致死锁
  5. 建议开发人员尽量使用更合理的业务逻辑,比如多表操作时以固定顺序访问表,尽量避免同时锁定多个资源
  6. 建议开发人员尽量保持事务简短,减少对资源的占用时间和占用范围
  7. 建议开发人员在读多血少的场景下采用乐观锁机制

死锁导致长时间阻塞的危害

众所周知,数据库的连接资源是很珍贵的,如果一个连接因为事务阻塞长时间不释放,那么后面新的请求要执行的sql也会排队等待,越积越多,最终会拖垮整个应用。一旦你的应用部署在微服务体系中而又没有做熔断处理(当某服务出现不可用或响应超时的情况时,会暂时停止对该服务的调用),由于整个链路被阻断,那么就会引发雪崩效应,导致很严重的生产事故。

MySQL 存储引擎

定义

存储引擎是MySQL数据库的组件,负责执行实际的数据IO操作(数据的存储和提取)。工作在文件系统之上,数据库的数据会先传输到存储引擎,再按照存储引擎的存储格式保存到文件系统。

常用存储引擎

InnoDB

InnoDB:支持事务处理、外键约束,缓存能力较好,支持行级锁定,读写并发能力较好,5.5版本后支持全文索引,适用于一致性要求高、数据更新频繁的应用场景。

MyISAM

MyISAM:不支持事务和外键约束,占用资源较小,访问速度快,表级锁定,支持全文索引,适用于不需要事务处理,单独写入或查询的应用场景。

MyISAM 和 InnoDB 的区别?

  • MyISAM:不支持事务、外键约束;支持全文索引;锁定类型只支持表级锁定;适合单独的查询和插入的操作;读写会相互阻塞;硬件资源占用较小;数据文件和索引文件是分开存储的,存储成三个文件:表结构文件.frm、数据文件.MYD、索引文件.MYI

使用场景:适用于不需要事务支持,单独的查询或插入数据的业务场景

  • InnoDB:支持事务、外键约束;也支持全文索引;锁定类型支持行级锁定(在全表扫描时仍会表级锁定);读写并发能力较好;缓存能力较好可以减少磁盘IO的压力;数据文件也是索引文件,存储成:表结构文件.frm、表空间文件.ibd

使用场景:适用于需要事务支持,数据一致性要求较高,数据会频繁更新,读写并发高的业务场景

InnoDB行锁与索引的关系

InnoDB的行级锁是通过给索引项加锁来实现的。如果对没有索引的字段进行操作会使用全表扫描并表级锁定。

MySQL 查询数据过程

  1. 客户端向 MySQL 服务器发送一条查询请求,连接器负责处理连接,并进行身份验证和权限控制。
  2. MySQL 先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果;否则使用查询解析器进行SQL语句解析、预处理,再由优化器生成对应的执行计划。
  3. MySQL 根据执行计划,调用存储引擎来执行查询。
  4. 将结果返回给客户端,同时缓存查询结果。

存储引擎的管理

查看系统支持的存储引擎

SHOW ENGINES;

在这里插入图片描述

查看表使用的存储引擎

  • play1
SHOW TABLE STATUS [FROM 库名] WHERE NAME='表名'

例:查看account表引擎

 show table status from mydb where name = 'account';
	##查看account表的存储引擎

在这里插入图片描述

  • play2
USE 库名;

SHOW CREATE TABLE 表名;

例:查看account表引擎

use mydb;
	##使用mydb库
	
show create table account;
	##查看account表的存储引擎

在这里插入图片描述

修改存储引擎

  • 通过 alter table 修改
USER 库名;

ALTER TABLE 表名 ENGINE=引擎名;

例:将account表的引擎修改为MyISAM

use mydb;
	##使用mydb库
	
alter table account engine=MyISAM;
	##修改account表的引擎为MyISAM

在这里插入图片描述

  • 通过修改 /etc/my.cnf 配置文件,指定默认存储引擎并重启服务
vim /etc/my.cnf
	......
	[mysqld]
	......
	default-storage-engine=引擎名

systemctl restart mysqld
##注意:此方法只对修改了配置文件并重启mysql服务后新创建的表有效,已经存在的表不会有变更。

例:将默认的引擎修改为MyISAM

## MySQL内
show engines;
##
##系统命令
vim /etc/my.cnf
	......
	[mysqld]
	......
	default-storage-engine=MyISAM
		##默认的引擎为MyISAM

systemctl restart mysqld
##
## MySQL内
show engines;
##

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 通过 create table 创建表时指定存储引擎
USER 库名;

CREATE TABLE 表名(字段1 数据类型,...) ENGINE=引擎名;

例:在mydb库中创建存储引擎为MyISAM的home表

use mydb
	##使用mydb库
create table home(id int, name varchar(50)) engine=MyISAM;
	##创建home表字段1为id,字段2为name

show create table home;
	##查看home表属性

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值