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

MySQL(二)、事务

程序员文章站 2024-03-23 12:45:40
...

目录

简介

特性

语法

脏读、幻读、不可重复读

脏读(Dirty Read)

幻读(Phantom Read)

不可重复读(Unrepeatable Read)

隔离级别


MySQL系列:

MySQL(一)、InnoDB索引原理及优化


简介

事务是"一组原子性的SQL命令",或者说一个独立的工作单元。如果数据库引擎能够成功地对数据库应用该组SQL的全部语句,那么就执行该组SQL。如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行。也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。

MySQL事务和锁https://dev.mysql.com/doc/refman/8.0/en/sql-transactional-statements.html

特性

事务具有以下4个特征,ACID

原子性(Atomicity):事务被视为一个不可分割的最小工作单元,事务中的所有操作要么全部提交成功,要么全部失败回滚;

一致性(Consistency):数据库总是从一个一致性的状态转换到另外一个一致性的状态;

隔离性(Isolation):一个事务所做的修改在最终提交以前,对其他事务是不可见的;

持久性(Durability):一旦事务提交,则其所做的修改就会永久保存到数据库中;

语法

自动提交事务:

默认情况下,MySQL开启了 autocommit 自动提交事务,若没有显式的开启事务则每个SQL都会被认为是一个事务自动执行提交操作。

show variables like "autocommit";

set autocommit=0; -- 或者OFF、False, 表示关闭自动提交
set autocommit=1; -- 或者ON、True, 表示开启自动提交

显式的管理事务:

如果想要显式的在事务中管理SQL,则可以使用下面的命令进行控制。

-- 开启一个事务
BEGIN 或 START TRANSACTION 

-- 提交事务,提交此事务中的所有动作;
COMMIT 或 COMMIT WORK

-- 回滚事务,撤销此事务内所有动作;
ROLLBACK 或 ROLLBACK WORK

-- 在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
SAVEPOINT identifier 

-- 删除事务的一个保存点;
RELEASE SAVEPOINT identifier 

-- 在事务中回滚到指定的保存点;
ROLLBACK TO identifier 

-- 设置事务的隔离级别,InnoDB存储引擎提供事务的隔离级别有:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE
SET TRANSACTION 

脏读、幻读、不可重复读

在多个事务并发操作时,数据库中会出现下面三种问题:脏读,幻读,不可重复读

脏读(Dirty Read

事务A读到了事务B还未提交的数据:

事务A读取的数据,事务B对该数据进行修改还未提交数据之前,事务A再次读取数据会读到事务B已经修改后的数据,如果此时事务B进行回滚或再次修改该数据然后提交,事务A读到的数据就是脏数据,这个情况被称为脏读(Dirty Read)。

MySQL(二)、事务

幻读(Phantom Read

事务A进行范围查询时,事务B中新增了满足该范围条件的记录,当事务A再次按该条件进行范围查询,会查到在事务B中提交的新的满足条件的记录(幻行 Phantom Row)。

MySQL(二)、事务

不可重复读(Unrepeatable Read

事务A在读取某些数据后,再次读取该数据,发现读出的该数据已经在事务B中发生了变更或删除。

MySQL(二)、事务

幻读和不可重复度的区别:

  • 幻读:在同一事务中,相同条件下,两次查询出来的 记录数 不一样;
  • 不可重复读:在同一事务中,相同条件下,两次查询出来的 数据 不一样; 

隔离级别

为了解决数据库中事务并发所产生的问题,在标准SQL规范中,定义了四种事务隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

MySQL事务隔离级别https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html

通过修改MySQL系统参数来控制事务的隔离级别,在MySQL8中该参数为 transaction_isolation ,在MySQL5中该参数为 tx_isolation :

MySQL8:
-- 查看系统隔离级别:
SELECT @@global.transaction_isolation;

-- 查看当前会话隔离级别
SELECT @@transaction_isolation;

-- 设置当前会话事务隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

-- 设置全局事务隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

事务的四个隔离级别:

  • 未提交读(READ UNCOMMITTED):所有事务都可以看到其他事务未提交的修改。一般很少使用;
  • 提交读(READ COMMITTED):Oracle默认隔离级别,事务之间只能看到彼此已提交的变更修改;
  • 可重复读(REPEATABLE READ):MySQL默认隔离级别,同一事务中的多次查询会看到相同的数据行;可以解决不可重复读,但可能出现幻读;
  • 可串行​​​​​(SERIALIZABLE):最高的隔离级别,事务串行的执行,前一个事务执行完,后面的事务会执行。读取每条数据都会加锁,会导致大量的超时和锁争用问题;

MySQL(二)、事务

问:如何保证 REPEATABLE READ 级别绝对不产生幻读?

:在SQL中加入 for update (排他锁) 或 lock in share mode (共享锁)语句实现。就是锁住了可能造成幻读的数据,阻止数据的写入操作。MySQL的 锁 相关的内容会在后面的篇章内详细介绍。

 

希望本文对你有帮助,请点个赞鼓励一下作者吧~ 谢谢!