MySql中的事务、MySql事务详解、MySql隔离级别
本文详细介绍了数据库事务的概念及操纵,包括事务的定义、开启、提交与回滚。一、什么是事务?
思考:我去银行给朋友汇款,我卡上有100元,朋友卡上50元,我给朋友转账50元,如果我的钱刚扣,而朋友的钱又没加时,网线断了, 怎么办?
事务:(Transaction)是数据库管理系统(DBMS)中的一个核心概念,它确保了一系列数据库操纵要么全部成功,要么全部失败,从而维护数据库的完备性和一致性。
MySQL在5.5版本开始,就将InnoDB引擎作为默认存储引擎。
由于Mysql中的事务是存储引擎实现,而且只有InnoDB支持事务 ,其他常见的如MyISAM和Memory都是不支持事务的,因此我们讲解InnoDB的事务。
二、事务四大特性ACID
[*]原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务内的操纵要么都发生,要么都不发生
[*]一致性(Consistency):事务前后数据的完备性必须保持一致
[*]隔离性(Isolation):多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离。隔离性由隔离级别保障!
[*]持久性(Durability):一个事务一旦提交,他对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
https://i-blog.csdnimg.cn/direct/1c661937c8284f4899c2af74611ce9d8.png
其中:原子性和一致性由undolog实现;隔离性由mvcc实现;持久性由redeolog实现
举个例子:
A向B转账500,转账成功,A扣除500元,B增加500元,原子操纵体如今要么都成功,要么都失败
在转账的过程中,数据要一致,A扣除了500,B必须增加500
在转账的过程中,隔离性体如今A向B转账,不能受其他事务干扰
在转账的过程中,持久性体如今事务提交后,要把数据持久化(可以说是落盘操纵)
2.1、原子性(Atomicity)
原子性:事务是一个不可分割的工作单位,事务中的操纵要么全部执行,要么全部不执行。这确保了事务的完备性,防止了部分操纵成功而部分操纵失败的环境。
[*]事务是一个完备的操纵,事务的各元素是不可分的。
[*]事务中的所有元素必须作为一个整体提交或回滚。
[*]如果事务中的任何元素失败,则整个事务将失败。
2.2、一致性(Consistency)
一致性:指在事务开始之前和事务竣事以后,数据库的完备性约束没有被粉碎。
[*]当事务完成时,数据必须处于一致状态 。
[*]在事务开始前,数据库中存储的数据处于一致状态。
[*]在正在举行的事务中,数据可能处于不一致的状态。
[*]当事务成功完成时,数据必须再次回到E知的一致状态。
2.3、隔离性(Isolation)
隔离性:指在并发环境中,当不同的事务同时利用类似的数据时,每个事务都有各自的完备数据空间。事务之间的操纵不会互干系扰。
[*] 对数据举行修改的所有并发事务是彼此隔离的,表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务。
[*] 修改数据的事务可在另一个使用类似数据的事务开始之前访问这些数据,或者在另一一个使用类似数据的事务竣事之后访问这些数据。
[*] 也就是说并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的。
[*] 隔离级别:
[*]未提交读(Read Uncommitted):答应脏读,即答应一个事务看到其他事务未提交的修改。这种隔离级别最低,性能最高,但一致性最差。
[*]提交读(Read Committed):只答应一个事务看到其他事务已经提交的修改。这种隔离级别可以防止脏读,但不能防止不可重复读和幻读。
[*]可重复读(Repeatable Read):确保如果在一个事务中执行两次类似的SELECT语句,都能得到类似的效果。这种隔离级别可以防止脏读和不可重复读,但不能完全防止幻读(在某些数据库系统中,如MySQL的InnoDB引擎,通过间隙锁等技术可以进一步防止幻读),MySQL默认事务级别。
[*]串行化(Serializable):将事务完全隔离,使得它们按顺序执行。这种隔离级别最高,一致性最好,但性能最低。
2.4、持久性(Durability)
持久性:指事务一旦提交,它对数据库所做的更改就会永久地生存在数据库中,即使系统发生故障也不会丢失。
[*]指不管系统是否发生故障,事务处理的效果都是永久的。
[*]一旦事务被提交,事务的效果会被永久地保留在数据库中。
总结:在事务管理中,原子性是底子,隔离性是手段,一致性是目的,持久性是效果。
三、事务操纵/事务的用法
3.1、事务操纵系列语法
[*]查看/设置事务提交方式
-- 查看会话级自动提交设置ON:开启自动提交OFF:禁用自动提交
show session variables like 'autocommit';
-- 注意:原命令中的 'lile' 应为 'like',查看全局级自动提交设置ON:开启自动提交OFF:禁用自动提交
show global variables like 'autocommit';
-- 查看/设置事务提交方式 1: 自动提交0:手动提交
select @@autocommit; -- 会显示 @@autocommit=1;默认为自动
--设置事务提交方式
set @@autocommit=0; -- 手动
https://i-blog.csdnimg.cn/direct/d1db8151e44042bf95abd7ffef4774dc.png
[*]开启事务
--开启事务
START TRANSACTION 或 BEGIN;
[*]提交事务
--提交事务
COMMIT ;
[*]回滚事务
--回滚事务
ROLLBACK;
[*]生存点
-- 设置保存点
SAVEPOINT;
-- 设置保存点并命名为S1
SAVEPOINT S1;
测试事务的使用及回滚
begin;
update account set money= money + 100 where name='A';
SAVEPOINT S1;
update account set money= money + 100 where name='B';
SAVEPOINT S2;
insert into account values(3,'C',1000);
select * from account;-- 查看当前状态
ROLLBACK TO S1;-- 回滚到S1点
select * from account;-- 查看回滚后的状态
在这个案例中,创建了多个回滚点,并举行了多次更新和插入操纵。然后,我们将事务回滚到S1 点,此时只有A的money字段被增加了100,而B的money字段和C的插入操纵都被撤销了。这意味着从S1点到事务竣事之间的所有操纵(更新B的money和插入C的记录)都被撤销了,而S1点之前的操纵(更新A的money)则保留了下来。
3.2、模仿转账失败(修改提交方式为手动)
数据预备
-- 数据准备
create table account(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '姓名',
money int comment '余额'
) comment '账户表';
insert into account(id, name, money) VALUES (null,'张三',2000),(null,'李四',2000);
-- 恢复数据操作
update account set money = 2000 where name = '张三' or name = '李四';
https://i-blog.csdnimg.cn/direct/63e9cdef1abc4df7967e1f055ca953ea.png
代码示例:
[*]如下方代码所示,我们用程序执行报错 ...模仿抛非常
[*]此时由于我们 设置为手动提交 set @@autocommit = 0; , 以是事务并未提交;
[*]后续rollback ; 回滚事务即可;
https://i-blog.csdnimg.cn/direct/091dba680d924bdb8c9da14dcb6113a1.png
-- 方式一
select @@autocommit;
set @@autocommit = 0; -- 设置为手动提交
-- 转账操作 (张三给李四转账1000)
-- 1. 查询张三账户余额
select * from account where name = '张三';
-- 2. 将张三账户余额-1000
update account set money = money - 1000 where name = '张三';
程序执行报错 ...//模拟抛异常
-- 3. 将李四账户余额+1000
update account set money = money + 1000 where name = '李四';
-- 提交事务
commit;
-- 回滚事务
rollback ;
四、并发事务题目(脏读-幻读-不可重复读)
4.1、并发事务概念
并发事务是指在数据库系统中,多个事务同时对数据举行读写和修改的过程。
对于同时运行的多个事务(多线程并发), 当这些事务访问数据库中类似的数据时, 如果没有接纳须要的隔离机制, 就会导致各种并发题目: (题目的本质就是线程安全题目,共享数据的题目)
应对步伐:
[*]事务隔离机制
[*]锁机制
[*]MVCC多版本并发控制隔离机制
4.2、并发事务题目
多个事务并发会导致什么题目呢?
题目描述脏写一个事务修改了另一个事务已经修改但尚未提交的数据。脏读一个事务读到了另一个事务还未提交的数据不可重复读一个事务读到了另一个事务已经提交(update) 的数据。引起事务中的多次查询效果不一致。虚读/幻读一个事务读到了另一个事务已经插入(insert) 的数据。导致事务中多次的查询效果不一致。 https://i-blog.csdnimg.cn/direct/388b9293b274495b8373057a8234f047.png
注意:√表现可能存在的题目 ,×表现解决该题目。
4.2.1、脏写/更新丢失
脏写:一个事务修改了另一个事务已经修改但尚未提交的数据。这种环境可能会导致数据不一致性和丢失更新的题目。
具体场景:具体来说,假设有两个事务A和B,事务A修改了某条数据,但还没有提交,此时事务B也修改了同一条数据并提交了。如许就会导致事务A的修改被覆盖或丢失,从而造成数据的不一致性。
示例:
https://i-blog.csdnimg.cn/direct/128a6b7f5db44cd49acb412355252fec.png
4.2.2、脏读
脏读:一个事务读到了另一个事务还未提交的数据。 脏读 (违背了事务的隔离性)
示例:
例:事务A先查询id为1的数据,再修改id为1的数据。修改完以后事务A还没提交,这时候事务B也来查询id为1的数据,但这时候事务B已经可以读到A修改完的数据了。这就是脏读。(如果A事务回滚,但B已经读到了A修改的数据,造成了数据不一致)
https://i-blog.csdnimg.cn/direct/38b0fb8d4f5e4a2097ff0eb2c7d31398.png
https://i-blog.csdnimg.cn/direct/759aac000c50495792434f94ef35ab5c.png
4.2.3、不可重复读
不可重复读: 一个事务读到了另一个事务已经提交(update) 的数据。引起事务中的多次查询效果不一致。不可重复读 (违背了事务的一致性)
例:事务A先查询id为1的数据,再执行某个逻辑。这时事务B修改id为1的数据。事务A再去查询id为1的数据,却和之前不一样了!简单来说就是:在同一个事务内,查询两次同一条数据,却出现不同效果!
https://i-blog.csdnimg.cn/direct/f060520d69534ad8aae7163a94b8b3d7.png
4.2.4、幻读
虚读/幻读: 一个事务读到了另一个事务已经插入(insert) 的数据。导致事务中多次的查询效果不一致。幻读 (违背了事务的隔离性)(在已经解决了不可重复读的底子上)
一个事务按类似的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种征象就称为“幻读”。
例:事务A查询id为1的数据,发现数据库中没有。这个时候事务B来了,恰恰往数据库中插入了一条id为1的数据并且提交了事务。这个时候,事务A举行插入操纵,就直接报错了:内里已经有了id为1的数据(假设我们已经解决了不可重复读的题目)。但A再次举行查询,查询效果和第一次一样,发现还是没有id为1的数据,但插入就是报错,这就是幻读的题目。
注意:幻读是在解决了不可重复读的底子上,不可重复读是读取了其他事务更改的数据,针对update操纵;幻读是读取了其他事务新增的数据,针对insert和delete操纵。
https://i-blog.csdnimg.cn/direct/5cc68d4e749a4dd8928e894b72d63640.png
五、事务隔离级别
数据库事务的隔离级别有4个,由低到高依次为:
[*]未提交读(Read Uncommitted):答应脏读,即答应一个事务看到其他事务未提交的修改。这种隔离级别最低,性能最高,但一致性最差。
[*]提交读(Read Committed):只答应一个事务看到其他事务已经提交的修改。这种隔离级别可以防止脏读,但不能防止不可重复读和幻读。
[*]可重复读(Repeatable Read)(mysql默认):确保如果在一个事务中执行两次类似的SELECT语句,都能得到类似的效果。这种隔离级别可以防止脏读和不可重复读,但不能完全防止幻读(在某些数据库系统中,如MySQL的InnoDB引擎,通过间隙锁等技术可以进一步防止幻读)。
[*]串行化(Serializable):将事务完全隔离,使得它们按顺序执行。这种隔离级别最高,一致性最好,但性能最低。
注意:事务隔离级别越高,数据越安全,但是性能越低。
这四个级别可以逐个解决脏写、脏读、不可重复读、幻读这几类题目。
隔离级别脏读不可重复读幻读READ UNCOMMITTED(读未提交)存在存在存在READ COMMITTED(读已提交)不存在存在存在REPEATABLE READ(可重复读)不存在不存在存在SERIALIZABLE(串行化)不存在不存在不存在
[*]以表格列举的顺序,从上到下,隔离级别越来越高,最高级别SERIALIZABLE强制事务按顺序执行,不答应并发。
[*]隔离级别越高,安全性越高,但性能越差。 选择合适的隔离级别尤为紧张,既要考虑安全性又要考虑性能。
[*]REPEATABLE READ(可重复读)只管没有完全解决幻读题目,但通过多版本并发控制(MVCC)和一种称为“Next-Key Lock”的技术解决了部分幻读题目。
我们在上面并发事务中提到了脏写,为什么在隔离级别中不存在脏写的题目了?
答:文上提到的4种隔离级别下,都不存在脏写环境。因为在这些隔离级别下,当两个事务A和B实验去更新同一条数据时,假定A先更新数据,会对更新的数据行记录加上排他锁(也叫写锁,悲观锁),除非事务A提交或停止从而开释排他锁,否则事务B都是无法更新数据的。(设计数据密集型应用只是说读提交隔离级别一定可以杜绝脏写题目,并未提到读未提交隔离级别,经过实践,读未提交下事务B的更新操纵也是需要等待事务A的排他锁开释,才得以执行)
5.1、查看、修改事务隔离级别
--查看事务隔离级别语法 【8.0+版本】【下面2条语句都可以查】
SELECT @@TRANSACTION_ISOLATION;
show variables like 'transaction_isolation';
--修改事务隔离级别语法
SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
-- 示例: 设置read committed级别:
set session transaction isolation level read committed;
设置 session 和 global 的区别:
[*]session(会话级):session参数仅在当前会话(或毗连)中有用
[*]global(全局级):global参数是全局的,意味着改变某个系统变量的值将会对所有会话都产生影响。 需要注意的是,一旦数据库服务重启,除非在设置文件(如my.cnf或my.ini)中举行了设置,否则这些全局变量的改变就会失效。
https://i-blog.csdnimg.cn/direct/9dbf55d7cd924da39bda973c023e11f2.png
六、总结
6.1、事务特性:
事务特性描述原子性把事务中的所有操纵看作为一个不可分割的工作单位,要么都执行,要么都不执行一致性包管事务开始前和事务竣事后数据的完备和一致隔离性使多个事务并发操纵同一个数据时,每个事务都有自己各自独立的数据空间,事务的执行不会受到别的事务干扰。可以通过设置隔离级别来解决不同的一致性题目持久性当事务被提交以后,事务中的命令操纵修改的效果会被持久化生存,且不会被回滚 6.2、隔离级别:
隔离级别答应的操纵类型备注未提交读 (Read Uncommitted)脏读、不可重复读、幻读最低级别的隔离,可能会读取到其他事务未提交的更改提交读 (Read Committed)不答应脏读,答应不可重复读、幻读只能读取到其他事务已经提交的更改,但同一事务内多次读取可能效果不同可重复读 (Repeatable Read)不答应脏读、不可重复读,有条件的答应幻读(使用InnoDB存储引擎可以解决)包管同一事务内多次读取效果一致,但某些环境下可能产生幻读,InnoDB通过间隙锁等方式解决串行读 (Serializable)都不答应(相当于锁表)最高级别的隔离,通过锁表包管事务的完全隔离,但会严峻影响数据库的并发性能 https://i-blog.csdnimg.cn/direct/388b9293b274495b8373057a8234f047.png
注意:√表现可能存在的题目 ,×表现解决该题目。
6.3、如何手动开启事务?【默认是主动commit的】
-- 1、显式声明开启事务
begin;
-- 2、输入需要执行的sql语句
update user set name ='李四' where name='lisi';
-- 3、提交事务
commit;
创作不易,接待打赏,你的鼓励将是我创作的最大动力。
https://i-blog.csdnimg.cn/direct/c69c1a11e6214f3da88ee63529e90cb2.jpeg
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]