MySQL事务

MySQL事务

一、事务分类

1、显式事务和隐式事务

(1)mysql的事务可以分为【显式事务】和【隐式事务】。默认的事务是隐式事务,由变量【autocommit】控制。隐式事务的环境下,我们每执行一条sql都会【自动开启和关闭】事务,变量如下:

(2)显式事务由我们【自己控制】事务的【开启,提交,回滚】等操作,我们创建一个表,同时展示事务的基础语法,如下:

create database test;

use test;

-- UNSIGNED代表无符号数,不能是负数

create table user(

id int primary key auto_increment,

name VARCHAR(20),

balance DECIMAL(10,2) UNSIGNED

);

insert into user VALUES (1,'cx',200);

insert into user VALUES (2,'王小美',50000);

-- 转账业务,必须都成功,或者都失败,所以不能一句一句执行,万一执行了一半,断电了咋办

-- 所以要编程一个整体

-- 如果所有的操作都成功并且你满意结果,你可以提交事务来永久保存所做的更改

-- 开启事务;

start transaction;

UPDATE user set balance = balance - 200 where id = 1;

UPDATE user set balance = balance + 200 where id = 2;

-- 提交事务

commit;

-- 如果有任何操作失败或者你不希望保留所做的更改,你可以回滚事务,这将会撤销自事务开始以来的所有更改

start transaction;

UPDATE user set balance = balance + 200 where id = 2;

UPDATE user set balance = balance - 200 where id = 1;

-- 回滚事务

rollback;

2、只读事务和读写事务

我们可以使用read only开启只读事务,开启只读事务模式之后,事务执行期间任何【insert】或者【update】语句都是不允许的,具体语法如下:

start transaction read only

select * from ....

select * from ....

commit;

保存点

我们可以使用savepoint 关键字在事务执行中新建【保存点】,之后可以使用rollback向任意保存点回滚。

start transaction;

UPDATE user set balance = balance - 200 where id = 1;

savepoint a;

UPDATE user set balance = balance + 200 where id = 2;

rollback to a;

Mysql是不支持嵌套事务的,开启一个事务的情况下,若再开启一个事务,会隐式的提交上一个事务:

start transaction;

UPDATE user set balance = balance - 200 where id = 1;

start transaction; -- 这里会自动将第一个事务提交

UPDATE user set balance = balance + 200 where id = 2;

commit;

-- 回滚事务

rollback;

二、事务四大特征(ACID)

1、原子性(Atomicity)

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

2、一致性(Consistency)

在事务【开始之前和结束以后】,数据库的完整性没有被破坏,数据库状态应该与业务规则保持一致。举一个例子:A向B转账,不可能A扣了钱,B却没有收到,也不可能A和B的总金额,在事务前后发生变化,产生数据不一致。其他的三个特性都在为他服务。

3、隔离性(Isolation)

数据库【允许多个并发事务同时对其数据进行读取和修改】,隔离性可以防止多个事务在并发修改共享数据时产生【数据不一致】的现象,这里要联想到多线程。

4、持久性(Durability)

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

三、脏读、不可重复读、幻读、解决方案

脏读 (Dirty Read)

定义:脏读是指一个事务能够读取另一个未提交事务修改的数据。如果第二个事务回滚了它的更改,那么第一个事务实际上读取到了从未实际存在的数据。例子:假设事务T1修改了一行数据,但尚未提交。此时事务T2读取了这一行被修改后的值。如果T1后来回滚了它的修改,那么T2实际上读取了一个从未存在过的状态。不可重复读 (Non-repeatable Read)

定义:不可重复读发生在同一事务内对同一行数据进行两次或多次读取时,其间另一事务对该行进行了修改并提交,导致不同的读取结果。例子:事务T1读取某一行的数据。然后,事务T2更新了这行数据,并提交了更改。当事务T1再次读取同一行时,它会得到不同的值,这就是不可重复读。幻读 (Phantom Read)

定义:幻读指的是在一个事务中执行相同的查询返回了不同的结果集。这通常是由于其他事务插入了新行或删除了现有行造成的。例子:事务T1基于某些条件执行了一个SELECT语句。接着,事务T2根据同样的条件插入了一些新的记录,并提交了这些更改。当事务T1重新执行之前的SELECT语句时,它可能会发现额外的“幻影”行。解决方案

为了防止上述问题的发生,SQL标准定义了四个事务隔离级别,按照严格程度递增排列为:

读未提交 (Read Uncommitted):允许脏读、不可重复读和幻读。读已提交 (Read Committed):禁止脏读,但允许不可重复读和幻读。可重复读 (Repeatable Read):禁止脏读和不可重复读,但允许幻读。序列化 (Serializable):完全禁止脏读、不可重复读和幻读,提供最高级别的隔离性,但可能导致更多的锁冲突和降低并发性能。四、并发事务隔离级别:

隔离级别脏读不可重复读幻读Read uncommitted(读未提交)√√√Read committed(读已提交)×√√Repeatable Read(可重复读)(默认)××√Serializable(串行化)××× 在mysql中查看和设置【事务的隔离级别】,语法如下:

-- 查看全局和当前事务的隔离级别

SELECT @@global.transaction_isolation, @@transaction_isolation_isolation;

show variables like 'transaction_isolation';

--5.7 tx_isolation

--8.0 transaction_isolation

-- 设置下一个事务的隔离级别

SET transaction isolation level read uncommitted;

SET transaction isolation level read committed;

set transaction isolation level repeatable read;

SET transaction isolation level serializable;

-- 设置当前会话的隔离级别

SET session transaction isolation level read uncommitted;

SET session transaction isolation level read committed;

set session transaction isolation level repeatable read;

SET session transaction isolation level serializable;

-- 设置全局事务的隔离级别

SET GLOBAL transaction isolation level read uncommitted;

SET GLOBAL transaction isolation level read committed;

set GLOBAL transaction isolation level repeatable read;

SET GLOBAL transaction isolation level serializable;

其中,SESSION 和 GLOBAL 关键字用来指定修改的事务隔离级别的范围:

SESSION:表示修改的事务隔离级别将应用于当前 session(当前 cmd 窗口)内的所有事务;

GLOBAL:表示修改的事务隔离级别将应用于所有 session(全局)中的所有事务,且当前已经存在的 session 不受影响;

如果省略 SESSION 和 GLOBAL,表示修改的事务隔离级别将应用于当前 session 内的下一个还未开始的事务。

1、读未提交(RU)

【ru隔离级别】说的简单一点就是,一个事务可以读取其他【未提交的事务】修改的数据,这种隔离级别最低,一般情况下,数据库隔离级别都要高于该级别,该隔离级别下,可能会存在脏读、不可重复度,幻读的问题。

2、读已提交(RC)

【RC读已提交】说的是当前事务只能读到别的事物已经提交的数据,该隔离级别可能会产生不可重复读和幻读。

3、可重复读(RR)

同一个事务中发出同一个SELECT语句【两次或更多次】,那么产生的结果数据集总是相同的,在RR隔离级别中可能出现幻读。

4、串行化

事务A和事务B,事务A在操作数据库时,事务B只能排队等待这种隔离级别很少使用,吞吐量太低,用户体验差这种级别可以避免“幻读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行,而不并发。

相关文章

世界杯往年揭幕战 世界杯历届揭幕战
365scores下载

世界杯往年揭幕战 世界杯历届揭幕战

🌱 07-13 💬 974
达摩(DAMO)
现金365

达摩(DAMO)

🌱 08-19 💬 288
群辉服务器怎么关机?
现金365

群辉服务器怎么关机?

🌱 08-09 💬 49