MySQL的事务特性和隔离机制—2023最新版

大纲

  • 什么是事务?
  • 事务的特性
  • 如何使用事务
  • 并发事务可能产生的问题
  • 事务的隔离机制
  • 如何设置事务隔离级别

什么是事务?

在了解事务的特性之前我们需要先了解一下什么叫事务和使用场景

事务(Transaction)是一个重要的概念。它是一组数据库操作,被视为一个单独的工作单元,要么全部成功执行,要么全部失败回滚,以保持数据的一致性和完整性。

举个例子:假设你在管理一个银行的数据库,你的数据库中有两个相关的表:一个存储账户信息的表(Account),一个存储交易历史的表(Transaction)。
你的任务是将一定金额从A账户转移到B账户。这一个操作涉及到两个数据库更新:A账户的余额减少,B账户的余额增加。在这种情况下,你可以将这两个更新操作放在一个事务中。
如果事务成功执行,那么金额会从一个账户转移到另一个账户,并且交易历史表中将记录这笔交易。
如果任何一个步骤失败(比如数据库连接中断账户余额不足等),整个事务将回滚,不会产生任何更改。

事务的特性

事务具有四个主要特性,通常被称为 ACID 特性,这些特性有助于确保数据库操作的一致性和可靠性:

  • 原子性(Atomicity): 原子性确保事务中的所有操作被视为一个不可分割的单元。要么所有操作都成功执行,要么如果其中任何一个操作失败,整个事务将被回滚,数据库将恢复到操作前的状态。这确保了数据库的一致性,避免了部分操作成功而部分操作失败的情况。

  • 一致性(Consistency): 一致性确保事务在执行之前和之后,数据库都保持一致的状态。事务操作必须遵守预定义的规则和完整性约束,以确保数据库的逻辑正确性。如果一个事务破坏了数据库的完整性,那么这个事务将被回滚,数据库状态将不会改变。

  • 隔离性(Isolation): 隔离性确保并发执行的多个事务相互隔离,使每个事务都感觉像是在独立地操作数据库。这样可以防止并发事务之间的相互干扰,避免了不一致性和并发问题。隔离性通过使用锁定机制和并发控制技术来实现。

  • 持久性(Durability): 持久性确保一旦事务提交成功,其所做的更改将永久保存在数据库中,即使系统崩溃也不会丢失。这是通过将事务的更改写入持久性存储(如磁盘)来实现的。这样,即使发生硬件故障或系统崩溃,数据也能够在恢复后保持一致。

这些 ACID 特性共同确保了事务的可靠性和数据库操作的一致性。然而,需要注意的是,有时候强制执行所有 ACID 特性可能会对性能产生影响,特别是在高并发环境下。因此,根据应用程序的需求,可能需要权衡事务的一致性和性能之间的关系。

如何使用事务

开始事务: 使用 BEGIN 命令来标志事务的开始。
执行操作: 在事务内,执行数据库操作,如插入、更新或删除数据。
提交事务: 如果所有操作都成功,使用 COMMIT 命令将事务提交,使所有操作永久性地应用到数据库中。
回滚事务: 如果任何操作失败或发生错误,使用 ROLLBACK 命令回滚事务,取消所有未提交的操作。

请注意,事务的使用需要满足以下条件:
数据库引擎必须支持事务,例如 InnoDB。
您的 MySQL 连接必须是一个事务连接。您可以使用 autocommit 参数来控制连接是否自动提交事务。

一般来说MySQL会默认开启自动提交策略,但是我们可以通过对应的设置来开启或者关闭自动提交。
不管有没有事务需求,我们一般也都建议设置为0,可以很大程度上提高数据库性能。

(1)注意:使用命令时应在mysql应用内
set autocommit=0;
set global autocommit=0;

(2)
cd /etc/ #进入etc目录
vim /etc/my.cnf #编辑配置文件
autocommit=0

以下是事务的使用事例

回滚事务,取消所有未提交的操作。

begin
delete from student where name='张三';
update student set name='张三' where name='李四';
rollback;

提交事务,使所有操作永久性地应用到数据库中。

begin
delete from student where name='张三';
update student set name='张三' where name='李四';
commit;

并发事务可能产生的问题

在许多事务处理同一个数据时,并发处理数据时,会带来一些的问题

那么会有哪些问题呢?这里的举例引用了SunAlwaysOnline大佬的博客内容

  • 脏读(Dirty Read): 脏读是指一个事务读取了另一个事务尚未提交的数据,导致读取到不正确的、尚未验证的数据。如果另一个事务回滚,则读取的数据实际上是无效的。

MySQL的事务特性和隔离机制—2023最新版_第1张图片

  • 不可重复读(Non-repeatable Read): 不可重复读是指在一个事务内,同一查询可能会多次读取不同的数据,因为在事务执行期间其他事务修改了数据。

MySQL的事务特性和隔离机制—2023最新版_第2张图片

  • 幻读(Phantom Read): 幻读是指在一个事务内,同一查询可能会多次读取不同数量的行,因为在事务执行期间其他事务插入或删除了数据。

MySQL的事务特性和隔离机制—2023最新版_第3张图片

事务的隔离机制

我们知道当数据库中同时运行多个事务时,可能会产生以上问题,那如何解决这个问题?这里我们引入事务隔离机制的概念

事务的隔离机制是指数据库系统如何处理并发事务以确保它们相互隔离,防止彼此之间的干扰和数据不一致性。在多个事务同时运行的情况下,隔离机制确保每个事务感觉像是在独立地操作数据库,避免了并发执行引起的问题。

数据库系统通过使用锁定、并发控制和事务隔离级别来实现隔离机制。有四个标准的事务隔离级别,每个级别提供了不同的隔离程度和并发控制策略:

  • 读未提交(Read Uncommitted): 最低级别的隔离,允许一个事务读取另一个事务尚未提交的数据。这可能会导致脏读、不可重复读和幻读等问题

  • 读已提交(Read Committed): 这是默认的隔离级别,要求一个事务只能读取已经提交的数据。这可以避免脏读,但仍然可能遇到不可重复读和幻读问题

  • 可重复读(Repeatable Read): 在这个级别下,一个事务在其生命周期内看到的数据保持一致。即使其他事务进行了修改和提交,这个事务读取的数据也不会发生变化,避免了不可重复读问题。但仍然可能遇到幻读问题,即某些行在同一事务中的不同查询中返回不同的结果。

  • 串行化(Serializable): 最高级别的隔离,确保事务彼此串行执行,避免了脏读、不可重复读和幻读等问题。但这可能会导致并发性能下降,因为事务需要等待其他事务完成。

这里用一张表方便可以更直观的了解他们的关系:

脏读 不可重复读 幻读
Read uncommitted
Read committed ×
Repeatable read × ×
Serializable × x x

如何设置事务隔离级别

MySQL支持多种事务隔离级别,用于控制并发事务对数据库中数据的影响程度。事务隔离级别包括:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。以下是设置MySQL事务隔离级别的方法:

在以下遇到的<隔离级别>可以替换为以下选项之一:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ或SERIALIZABLE。对应关系可以参阅上面表格。

1. 通过SQL语句设置事务隔离级别:

你可以在事务开始之前,通过以下SQL语句来设置事务隔离级别:

SET TRANSACTION ISOLATION LEVEL <隔离级别>;

2. 在BEGIN或START TRANSACTION语句中设置隔离级别:

在开始事务时,你也可以在BEGIN或START TRANSACTION语句中直接设置隔离级别:

BEGIN;
-- 或者
START TRANSACTION;

然后,可以通过下面的语句来设置隔离级别:

SET TRANSACTION ISOLATION LEVEL <隔离级别>;

3. 配置默认隔离级别:
如果你想要为整个MySQL实例设置默认隔离级别,可以在MySQL的配置文件(通常是my.cnf或my.ini)中进行设置。
找到[mysqld]部分,并添加或修改以下行来设置默认隔离级别:

transaction-isolation = <隔离级别>

重启MySQL服务器以使更改生效。

ps:本文章旨在为小白快速了解和使用事务,如有不详之处请谅解并指出,我会及时改正!

你可能感兴趣的:(数据库,mysql,数据库)