欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Mysql的事务特性,四种隔离级别及原理

程序员文章站 2022-06-14 18:56:53
...

一、事务的基本要素(ACID)

1、原子性(Atomicity)

事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

2、一致性(Consistency)

事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

3、隔离性(Isolation)

同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

4、持久性(Durability)

事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

二、事务隔离级别的查看和修改

事务隔离级别的查看:
mysql8之前:

select @@GLOBAL.tx_isolation;
select @@tx_isolation;

mysql8之后

select @@GLOBAL.transaction_isolation;
select @@transaction_isolation;

事务隔离级别的修改

set session transaction isolation level repeatable read;
set session transaction isolation level serializable;
set session transaction isolation level read committed;
set session transaction isolation level read uncommitted;

三、事务的四种隔离级别

1、Serializable 串行化

事务之间的执行是一个执行完另一个再执行,每次只执行一个

2、repeatable-read 可重复读

Mysql的默认事务隔离级别
一个正在执行的事务的变化,不能被其他事务所看见

例如一个真在执行的事务A:

START TRANSACTION;
SELECT grade from user WHERE username='zhangsan';
SELECT grade from user WHERE username='zhangsan';
COMMIT;

执行到第一句查询sql时,zhangsan的grade=10,
这时另一个事务B修改了zhangsan的grade并提交

start transaction;
update user set grade=30 where username='zhangsan';
commit;

此时事务A执行第二句查询sql,zhangsan的grade也为10,并未改变

可重复读会出现幻读的问题:
给username增加unique约束
当事务A刚开启:

START TRANSACTION;
SELECT grade from user WHERE username='wangwu';
insert into user(grade,username) values (15,'wangwu');
COMMIT;

此时事务B执行并提交,插入数据wangwu:

start transaction;
insert into user(grade,username) values (15,'wangwu');
commit;

再继续执行事务A,此时事务A既查询不到wangwu的数据,也无法插入wangwu的数据,出现幻读

3.read-committed读已提交

处于不可重复读级别的事务,可以看到其他已经提交的事务对数据的修改。也就是说,如果其他事务修改了相应的表,那么同一个事务中多个sql语句查询同一条数据可能返回不同的结果

也会出现幻读的问题
例子和上面相同

4.read-uncommitted读未提交

处于读未提交隔离级别的事务,可以读到其他事务执行但未提交的数据,会产生脏读和幻读
幻读:
事务A开启:

start transaction;
select * from user where username='zhaoliu';
delete from user where username='zhaoliu';
commit;

此时事务B开启并执行插入zhaoliu的语句但未提交

START TRANSACTION;
insert into user(grade,username) values (15,'zhaoliu');
COMMIT;

此时事务A执行查询zhaoliu和删除zhaoliu的语句,可以查询到,但是不能删除,因为事务B还未提交,这就会出现幻读

脏读:
一个事务可以查看到您一个事务还未提交的数据,但一但另一个事务发生回滚,这个事务就会出错.

4、原理(MVCC)

先看MVCC简单理解
再看MVCC具体剖析
MVCC如何实现数据库读已提交和可重复读这两种隔离级别?