MySQL事务、存储引擎

ops/2024/10/15 22:18:57/

目录

一、事务

1.1 事务的概念

1.2 事务的ACID特点

1.2.1 原子性

1.2.2 一致性

1.2.3 隔离性

1.2.4 持久性

1.3 事务控制语句

1.4 使用 set 设置控制事务

二、存储引擎

2.1 存储引擎的定义

2.2 常用的存储引擎

2.3 存储引擎的管理操作

三、死锁

3.1 定义

3.2 死锁的危害

3.3 如何尽可能避免死锁


一、事务

1.1 事务的概念

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

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

1.2 事务的ACID特点

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

1.2.1 原子性

        指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。事务是一个完整的操作,事务的各元素是不可分的。事务中的所有元素必须作为一个整体提交或回滚。如果事务中的任何元素失败,则整个事务将失败。

案例:

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

1.2.2 一致性

        指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。当事务完成时,数据必须处于一致状态。在事务开始前,数据库中存储的数据处于一致状态。在正在进行的事务中,数据可能处于不一致的状态。当事务成功完成时,数据必须再次回到已知的一致状态。

案例:

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

1.2.3 隔离性

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

当多个客户端并发地访问同一个表时,可能出现下面的一致性问题:

  • 脏读:当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
  • 不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)
  • 幻读:一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,另一个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,操作前一个事务的用户会发现表中还有一个没有修改的数据行,就好象发生了幻觉一样。
  • 丢失更新:两个事务同时读取同一条记录,A先修改记录,B也修改记录(B不知道A修改过),B提交数据后B的修改结果覆盖了A的修改结果。

事务的隔离级别决定了事务之间可见的级别。

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

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

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

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

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

mysql默认的事务处理级别是 repeatable read ,而Oracle和SQL Server是 read committed 。

//事务隔离级别的作用范围分为两种:

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

查询全局事务隔离级别:

show global variables like '%isolation%';

 查询会话事务隔离级别:

show session variables like '%isolation%';

设置全局事务隔离级别:

set global transaction isolation level read committed;            #重启服务后失效

 

 设置会话事务隔离级别:

set session transaction isolation level repeatable read;

 

1.2.4 持久性

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

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

1.3 事务控制语句

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

1.4 使用 set 设置控制事务

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

 

如果没有开启自动提交,当前会话连接的mysql的所有操作都会当成一个事务直到你输入rollback|commit;当前事务才算结束。当前事务结束前新的mysql连接时无法读取到任何当前会话的操作结果。
如果开起了自动提交,mysql会把每个sql语句当成一个事务,然后自动的commit。
当然无论开启与否,begin; commit|rollback; 都是独立的事务。

二、存储引擎

2.1 存储引擎的定义

  • 存储引擎时MySQL数据库的一个核心组件,负责执行实际的数据IO操作(数据的存储和提取)。

  • 工作在文件系统之上数据库的存储数据会将数据传输到存储引擎,再按照存储引擎的存储格式保存到文件系统。

2.2 常用的存储引擎

常用的存储引擎:InnoDB MyISAM

  • MyISAM不支持事务和外键约束,占用资源较小,访问速度快,只支持表级锁定读写会相互阻塞,支持全文索引。适用于不需要事务处理,单独写入或查询的应用场景。存储为三个文件:表结构文件 .frm   表数据文件 .MYD     索引文件 .MYI
  • InnoDB支持事务和外键约束缓存能力较好支持行级锁定读写并发能力较好,5.5版本后开始支持全文索引。适用于需要事务支持,一致性要求高,数据更新频繁的应用场景

    InnoDB行级锁定是通过索引来实现的,在全表扫描时仍是表级锁定

    存储为两个文件:表结构文件 .frm    表空间文件 .ibd

MyISAM 表支持 3 种不同的存储格式:

(1)静态(固定长度)表

        静态表是默认的存储格式。静态表中的字段都是非可变字段,这样每个记录都是固定长度的,这种存储方式的优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多。

(2)动态表

        动态表包含可变字段,记录不是固定长度的,这样存储的优点是占用空间较少,但是频繁的更新、删除记录会产生碎片,需要定期执行 OPTIMIZE TABLE 语句或 myisamchk -r 命令来改善性能,并且出现故障的时候恢复相对比较困难。

(3)压缩表

        压缩表由 myisamchk 工具创建,占据非常小的空间,因为每条记录都是被单独压缩的,所以只有非常小的访问开支。

2.3 存储引擎的管理操作

#查看系统支持的存储引擎

show engines;

#查看表使用的存储引擎

方法一:

show table status from 库名 where name='表名'\G

方法二:

use 库名;
show create table 表名;

#修改存储引擎

1.通过 alter table 修改
use 库名;
alter table 表名 engine=MyISAM;

 

2.通过修改 /etc/my.cnf 配置文件,指定默认存储引擎并重启服务
vim /etc/my.cnf
......
[mysqld]
......
default-storage-engine=INNODBsystemctl restart mysql.service
注意:此方法只对修改了配置文件并重启mysql服务后新创建的表有效,已经存在的表不会有变更。

 

3.通过 create table 创建表时指定存储引擎
use 库名;
create table 表名(字段1 数据类型,...) engine=MyISAM;

补充:InnoDB行锁与索引的关系
InnoDB行锁是通过给索引项加锁来实现的。

1)
delete from t1 where id=1;    
如果id字段是主键,innodb对于主键索引,会直接锁住整行记录。

2)
delete from t1 where name='aaa';
如果name字段是普通索引,会锁住索引的两行记录。

3)
delete from t1 where age=23;
如果age字段没有索引,会使用全表扫描过滤,这时表上的各行记录都将加上锁。

三、死锁

3.1 定义

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

例如:

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

3.2 死锁的危害

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

 案例:

create table t1(id int primary key, name char(3), age int);
insert into t1 values(1,'aaa',22);
insert into t1 values(2,'bbb',23);
insert into t1 values(3,'aaa',24);
insert into t1 values(4,'bbb',25);
insert into t1 values(5,'ccc',26);
insert into t1 values(6,'zzz',27);session 1											session 2
begin;											
select * from t1 where id=1 for update;				begin;select * from t1 where id=2 for update;
select * from t1 where id=2 for update;#等待		select * from t1 where id=1 for update;#死锁发生

#for update 可以为数据库中的行上一个排它锁。当一个事务的操作未完成时候,其他事务可以读取但是不能写入或更新。


#共享锁:又叫做读锁,当用户要进行数据的读取时,对数据加上共享锁,共享锁可以同时加上多个。


#排他锁:又叫做写锁,当用户要进行数据的写入时,对数据加上排他锁,排他锁只可以加一个,它和其它的排他锁,共享锁都相斥。

3.3 如何尽可能避免死锁

1)设置锁等待超时时间:即两个事务相互等待时,一旦等待时间超过了这个时间之后,那么超时事务回滚释放资源,另一个事务就能正常执行了。
在 InnoDB 存储引擎中,参数 innodb_lock_wait_timeout 是用来设置超时时间的,默认值为 50 秒。 show VARIABLES like 'innodb_lock_wait_timeout';
参数 innodb_rollback_on_timeout 表示是否在等待超时时对进行中的事务进行回滚操作(默认是OFF,代表不回滚)。

2)主动开启死锁检测:当 innodb 检测发现死锁之后,就会进行回滚死锁的事物。
show VARIABLES like  'innodb_deadlock_detect';         #查看当前死锁检测是否开启
set global innodb_deadlock_detect = ON;                #ON为开启死锁检测,OFF为关闭

3)使用更合理的业务逻辑。对于数据库的多表操作时,尽量按照相同的顺序进行处理,尽量避免同时锁定多个资源。

4)保持事务简短。减少对资源的占用时间和占用范围,避免长事务,减少完成事务可能的延迟并释放锁。

5)为表添加合理的索引。如果不使用索引将会发生全表扫描,扫描时间长,占用资源多,且耗时,会导致死锁的概率大大增加。    


6)降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为间隙锁造成的死锁。

7)读多写少的场景下使用乐观锁机制,读取数据不上锁,在读的情况下可以共享资源,这样可以省去了锁的开销,提高了吞吐量。

#乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据,如果别人修改了数据则放弃操作,否则执行操作。适用于读多写少的场景。
SELECT * from t1 where id = 1 lock in share MODE;


#悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。一般适用于写多的场景。
SELECT * from t1 where id = 1 for update;


http://www.ppmy.cn/ops/126141.html

相关文章

【git】本地玩坏了不必重新clone

#没错,事情发生的起因就是我把本地玩坏了……然后傻乎乎地打算rm掉重新再clone,巨慢真的,然后我就又被涨知识了,分享一下,如果已经知道的就笑笑路过吧哈哈哈# 场景 需要重新clone的,恢复到与远端仓库一致…

站在用户视角审视:以太彩光与PON之争

作者:科技作家-郑凯 园区,是企业数字化转型的“中心战场”。 云计算、大数据、人工智能等数智化技术在园区里“战火交织”;高清视频、协同办公,智慧安防等大量创新应用产生的海量数据在园区内“纵横驰骋”;加上大量的IOT和智能化设备涌入“战场”,让园区网络面对着难以抵御的…

【Java 问题】集合——List

List 1.说说有哪些常见集合?2.ArrayList和LinkedList有什么区别?3.ArrayList的扩容机制了解吗?4.ArrayList怎么序列化的知道吗? 为什么用transient修饰数组?5.快速失败(fail-fast)和安全失败(fail-safe)了解吗&#xf…

代码随想录算法训练营第三十五天|452. 用最少数量的箭引爆气球 435. 无重叠区间 763.划分字母区间

452. 用最少数量的箭引爆气球 在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结…

Java 包装器一口气讲完!(≧∇≦)ノ

目录 Java 数据类型包装器 Java数据类型教程 - Java数据类型包装器 方法 例子 valueOf() Java 数字数据类型 Java数据类型教程 - Java数字数据类型 例子 方法 值 Java 字符数据类型 Java数据类型教程 - Java字符数据类型 例子 Java Boolean包装类 Java数据类型教程…

windows C++-避免死锁(下)

使用 join 防止死锁 下面介绍了如何使用消息缓冲区和消息传递函数来消除死锁的可能性。 为了将该示例与上一示例相关联,philosopher 类通过使用 concurrency::unbounded_buffer 对象和 join 对象来替换每个 critical_section 对象。 join 对象充当为哲学家提供筷子…

mac下docker的详细安装和配置

linux的docker安装请参考:linux下docker详细安装,在Mac上安装Docker也相对简单,以下是详细步骤: 1. 系统要求 确保你的Mac满足以下要求: macOS 10.14(Mojave)或更高版本至少4GB RAM 2. 下载…

img标签的title和alt的区别,png、jpg、gif、格式区别

img标签的title和alt有什么区别? 区别一: title:鼠标移入到图片显示的值 alt:图片无法加载时显示的值 区别二: 在seo的层面上,蜘蛛抓取不到图片的内容,所以前端在写img标签的时候为了增加seo效果…