MySQL的数据库事务、ACID特性以及实践案例

AI 概述
什么是数据库事务,为什么它如此重要?MySQL 及其事务支持事务的 ACID 特性原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability)MySQL 事务中的锁和并发控制如何在 MySQL 中创建与使用事务如何在 MySQL 事务中使用 InnoDB 存储引擎如何处理事务中的错误和异常如何在 MySQL 事...
目录
文章目录隐藏
  1. 什么是数据库事务,为什么它如此重要?
  2. MySQL 及其事务支持概述
  3. 事务的 ACID 特性
  4. MySQL 事务中的锁和并发控制
  5. 如何在 MySQL 中创建与使用事务
  6. 如何在 MySQL 事务中使用 InnoDB 存储引擎
  7. 如何处理事务中的错误和异常
  8. 如何在 MySQL 事务中使用保存点(Savepoints)
  9. 小结

MySQL 的数据库事务、ACID 特性以及实践案例

什么是数据库事务,为什么它如此重要?

数据库事务是数据库中一个操作单元,包含一组被整体执行和写入的多个数据操作。这些操作可以包括创建(Create) 、读取(Read) 、更新(Update) 或删除(Delete) 操作。

事务过程中的数据处于不一致的状态,因为事务正在对数据库进行修改。一旦事务中的所有操作被提交(Commit) ,数据库就会恢复到一致的状态。

通俗的讲,在一个数据库事务中的一个或多个 SQL 操作,要么都执行成功,要么都执行失败。

数据库事务在确保多个操作同时执行时数据库的一致性方面非常重要。同时,它还提供了一种恢复由于操作失败或误操作导致数据更改的方法。

MySQL 及其事务支持概述

MySQL 数据库支持通过提供相关语句的形式来实现数据库事务。

MySQL 支持以下内置操作语句:

  • START TRANSACTION/BEGIN:触发事务的开始。
  • COMMIT:提交事务,使得对数据库产生的修改变为永久性。

可以通过以下语句设置数据库自动提交更改:

SET autocommit = 1;

SET:用于设置事务提交方式,可以启用事务的自动提交,也可以禁用自动提交。当禁止自动提交时,只有执行COMMIT语句后操作才会提交。

/*禁用自动提交*/
SET autocommit = 0;
/*或者*/
SET autocommit = OFF;

/*启用自动提交每一个操作*/
SET autocommit = 1;
/*或者*/
SET autocommit = ON;

ROLLBACK:可用于撤销对数据库所做的更改,从而将数据库返回到操作之前的状态(最近的提交状态)。

事务的 ACID 特性

ACID 表示原子性(Atomicity) 、一致性(Consistency) 、隔离性(Isolation) 和持久性(Durability)  。我们来逐个了解每个特性在事务中的含义。

原子性(Atomicity)

原子性意味着在数据库事务中发生的所有更改会被视为一个整体。这意味着在试图修改数据库时,所有更改要么同时发生,要么完全不发生。

就好比你和你的团队在构建一个应用程序。如果一个人写了一行代码,然后另一人删除了这一行代码,就好像什么都没有发生过。但如果每个人都添加了不同的代码,而且没有人删除代码,那么代码库就会逐渐变大。

一致性(Consistency)

一致性表示数据库中存储的数据始终处于有效和一致的状态。例如,如果数据库包含任何约束(如主键、外键等),则这些数据必须遵循相关约束规则。

举个例子,假设某个表有一个规则,规定特定列必须是整数值。一致性确保这些规则始终得到遵守,插入到该列中的数据只能是整型数据类型。

隔离性(Isolation)

隔离性是指多个事务可以在不互相干扰的情况下执行。事务的隔离级别决定了一个事务所做的更改对其他事务的可见性。

MySQL 支持以下隔离级别:

  1. READ UNCOMMITTED:在这个隔离级别(最低级别),一个事务可以读取其他事务尚未提交的数据。这意味着,其他事务可以修改当前事务正在读取的数据,但这些更改可能直到操作完成后才可见。
  2. READ COMMITTED:在次低的隔离级别下,一个事务只能读取其他事务已经提交的数据。其他事务可以修改当前事务正在读取的数据,但这些更改要等到修改后的事务提交后才会可见。
  3. REPEATABLE READ:这是更高级的隔离级别。在此级别,一个事务只能读取其他事务已经提交的数据,且会限制其他事务修改当前事务正在读取的数据。这意味着,即使其他事务提交了更改,如果某个事务再次执行SELECT语句,它会依旧看到同一数据。
  4. SERIALIZABLE:这是最高的隔离级别。在此级别,一个事务只能读取其他事务已经提交的数据,并且防止其他事务修改该事务所读取的数据,以及添加新行(这些新行对当前事务不可见)。

默认情况下,MySQL 使用READ COMMITTED隔离级别。另外,可以通过SET TRANSACTION ISOLATION LEVEL语句来改变隔离级别。

持久性(Durability)

持久性确保即使发生意外情况(例如故障或断电),事务的更改也会保存在数据库中。一旦事务被提交,其更改必须永久存储。

MySQL 通过写前日志(Write-Ahead Logging, WAL) 机制保证持久性。这种技术在对数据库进行修改之前,会先将事务日志写入磁盘。

该日志充当数据库的“路线图”,包含将在意外系统故障时如何重新进行更改的信息。因此数据库可以从日志中恢复,并重放事务中所做的更改,以确保数据一致性。

需要注意的是,虽然写前日志可能影响性能,但能保证数据安全却是值得付出的代价。

MySQL 事务中的锁和并发控制

锁定是为了防止竞争条件的一种技术。竞争条件指的是多个事务尝试同时访问相同数据的情况。

MySQL 使用以下几种锁来控制事务中的数据访问:

  1. 共享锁(Shared Locks) :允许多个事务同时读取相同数据,但禁止任何事务对数据进行修改。
  2. 独占锁(Exclusive Locks) :防止不同事务同时读取或修改相同数据。
  3. 意向锁(Intent Locks) :用于标志一个事务计划读取或写入某部分数据。
  4. 行级锁(Row-level Locks) :允许事务仅锁定它需要访问的特定行,而不是锁定整个表。

并发是允许多个事务同时运行,并且不会干扰彼此数据的方法。

MySQL 使用多版本并发控制(MVCC, Multi-Version Concurrency Control) 机制,允许多个事务同时读取和写入相同的数据而不会冲突。

这如何实现呢?每个事务在开始时会“捕获”将要修改的数据,并将其更改写入完全不同的版本,这样其他事务可以继续使用原始版本的数据,不会发生冲突。

要实现高并发,务必保持事务尽可能短,并避免长期运行的事务,以免长时间占用锁。

如何在 MySQL 中创建与使用事务

进行事务操作的第一步是通过START TRANSACTION语句启动一个事务。示例如下:

START TRANSACTION;
    INSERT INTO users (name, email) VALUES ('师兄奇谈', 'shixiongqitan@example.com');
    UPDATE accounts SET balance = SUM(balance) WHERE name = '师兄奇谈';

在这个例子中,用START TRANSACTION语句开启一个新事务。之后的两个语句 (INSERTUPDATE) 都是在此事务内执行的。

为了使更改永久保存,我们需要通过COMMIT语句提交更改:

START TRANSACTION;
    INSERT INTO users (name, email) VALUES ('师兄奇谈', 'shixiongqitan@example.com');
    UPDATE accounts SET balance = SUM(balance) WHERE name = '师兄奇谈';
COMMIT;

如果在事务过程中出现错误,想撤销更改,可以使用ROLLBACK语句。事务会被回滚,插入和更新语句不再执行,数据库数据不会发生改变。

START TRANSACTION;
    INSERT INTO users (name, email) VALUES ('师兄奇谈', 'shixiongqitan@example.com');
    UPDATE accounts SET balance = SUM(balance) WHERE user_id=15;
ROLLBACK;

如何在 MySQL 事务中使用 InnoDB 存储引擎

InnoDB 是 MySQL 的一个存储引擎,提供了许多可提升数据库性能的功能,例如支持组装和执行多个 SQL 语句、加密数据、创建/删除索引而不影响数据库性能、良好的 CPU 及大数据处理能力等等。

要在 MySQL 中使用 InnoDB 进行事务操作,需要确保表使用的是 InnoDB 存储引擎。可以通过运行下面的查询来检查:

SHOW TABLE STATUS FROM your_database_name;

可以通过修改my.cnf配置文件设置默认存储引擎为 InnoDB,或者运行以下命令:

SET storage_engine=InnoDB;

如何处理事务中的错误和异常

在事务中处理错误和异常至关重要。处理错误的一种常见方法是在 MySQL 中使用SIGNALRESIGNAL语句,并结合异常处理。

以下是用TRY-CATCH结构处理事务异常的一个示例:

START TRANSACTION;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
    ROLLBACK;
UPDATE accounts SET balance = 5000 WHERE user_id = 1;
UPDATE accounts SET balance = 1000 WHERE user_id = 2;
IF (SELECT balance FROM accounts WHERE user_id = 1) < 0 THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Insufficient balance';
END IF;
COMMIT;

如果在事务中发生了异常,将使用ROLLBACK撤销事务内的所有更改。SIGNAL语句可以用于在事务中自定义异常消息。

一旦事务内发生异常,不管是否处理,事务中的所有更改都会被回滚。

如何在 MySQL 事务中使用保存点(Savepoints)

在事务中使用SAVEPOINT语句可以设置保存点(savepoint) ,以允许事务回滚到特定的时间点,而不是回滚整个事务。

例如:

START TRANSACTION;
SAVEPOINT my_savepoint;
UPDATE accounts SET balance = 5000 WHERE user_id = 1;
UPDATE accounts SET balance = 1000 WHERE user_id = 2;
IF (SELECT balance FROM accounts WHERE user_id = 1) < 0 THEN
    ROLLBACK TO SAVEPOINT my_savepoint;
END IF;
COMMIT;

在 SAVEPOINT语句定义了一个命名为my_savepoint的保存点。如果在事务中捕获到异常,可以用ROLLBACK TO SAVEPOINT my_savepoint撤销保存点后的更改,而保留保存点之前的更改。

小结

这篇文章我们从整体上介绍了什么是数据库事务,数据库事务的 ACID 特征,以及在事务中涉及到的并发锁、MVCC 等基础概念,最后通过具体的案例说明了如何开启和回滚事务。这篇文章只是整体的概述,在后续的文章中,我们会针对上述的内容详细展开讲解,记得持续关注。

文章来源:公众号师兄奇谈

以上关于MySQL的数据库事务、ACID特性以及实践案例的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » MySQL的数据库事务、ACID特性以及实践案例

发表回复