深入了解MySQL的事务ACID原则

Posted @paopao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入了解MySQL的事务ACID原则相关的知识,希望对你有一定的参考价值。

前言

mysql是一种关系型数据库管理系统,而事务是MySQL中非常重要的一个概念。在开发Web应用程序时,使用事务可以确保操作的原子性、一致性、隔离性和持久性,以避免数据不一致的情况发生。在这篇文章中,我们将介绍MySQL中的事务ACID原则。

 什么是事务?

在数据库系统中,事务是一个逻辑单元,它由一组操作组成,这些操作必须作为一个整体来执行。事务有四个关键属性,分别是原子性、一致性、隔离性和持久性(ACID)。

事务的ACID原则 

  • 原子性(Atomicity):一个事务必须被视为一个不可分割的原子操作,要么全部执行成功,要么全部执行失败。如果一个事务的一部分操作失败,那么整个事务都将被回滚到原始状态,从而确保数据库的一致性。

  • 一致性(Consistency):在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏。换句话说,一个事务必须使数据库从一个一致性状态变到另一个一致性状态。例如,在转账操作中,如果一个账户的余额被减少,另一个账户的余额必须相应地增加,以保持数据库的一致性。

  • 隔离性(Isolation):事务之间必须相互隔离。这意味着一个事务所做的修改在提交之前对其他事务是不可见的。这可以防止数据竞争和其他并发问题。例如,当两个事务同时尝试修改同一行数据时,隔离性可以确保每个事务只能看到自己所做的修改,而不是其他事务的修改。

  • 持久性(Durability):一旦事务提交,它所做的修改就会被永久保存到数据库中,并且即使系统崩溃,这些修改也不应该被丢失。例如,如果一个用户购买了一件商品,那么这个购买操作必须被永久保存在数据库中,即使系统崩溃或重启。

  • 隔离产生的问题(注意)

    脏读:指一个事务读取了另外一个事务未提交的数据。

    不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对)

    虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
    (一般是行影响,多了一行)

 MySQL中的事务

MySQL是一种关系型数据库管理系统,支持事务。MySQL中的默认存储引擎是InnoDB,这个存储引擎支持事务。在MySQL中,可以使用以下语句来定义和管理事务:

START TRANSACTION;
-- SQL statements
COMMIT;

 这个语句序列包含一个START TRANSACTION语句,它表示事务的开始,并且COMMIT语句表示事务的结束。如果需要回滚事务,则可以使用ROLLBACK语句。

执行事务

-- mysql 自动开启事务提交
SET autocommit=0 -- 关闭
SET autocommit=1 -- 开启(默认的)

-- 手动处理事务
SET autocommit =0 -- 关闭自动提交

-- 事务开启

START TRANSACTION -- 标记一个事务的开始,从这个之后的SQP都在同一个事务内

INSERT XX
INSERT XX

-- 提交 : 持久化(成功)
COMMIT 
-- 回滚:  回到原来的样子(失败)
ROLLBACK
-- 事务结束
SET autocommit = 1 -- 开启自动提交
-- 了解
SAVEPOINT 保存点名称 -- 设置一个事务的保存点
ROLLBACK TO SAVEPOINT 保存点名 -- 回滚到保存点
RELEASE SAVEPOINT 保存点 -- 删除保存点

模拟场景

CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_general_ci
USE shop
CREATE TABLE `account`(
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO account(`name`,`money`)
VALUES('A',2000),('B',10000)

-- 模拟转账:事务
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION -- 开启事务(一组事务)
UPDATE account SET money = money-500 WHERE `name` = 'A' -- A 转账给B
UPDATE account SET money = money+500 WHERE `name` = 'B' -- B 收到钱

COMMIT ; -- 提交事务
ROLLBACK ; -- 回滚

SET autocommit=1 -- 恢复默认值

事务的隔离级别 

在MySQL中,事务的隔离级别有四个,分别是READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。这些隔离级别可以通过设置事务的隔离级别来控制事务之间的并发访问和数据修改。以下是每个隔离级别的特点:

  • READ UNCOMMITTED:允许事务读取未提交的数据。在这个隔离级别下,事务可以看到其他事务未提交的修改,这可能会导致“脏读”(读取到未提交的数据)和“不可重复读”(读取到不同的数据,因为另一个事务已经修改了它们)。

  • READ COMMITTED:允许事务读取已提交的数据。在这个隔离级别下,事务只能看到其他已经提交的事务所做的修改。这可以防止脏读,但可能会导致不可重复读,因为另一个事务可能会提交一个修改,而这个修改会影响到该事务正在读取的数据。

  • REPEATABLE READ:确保事务内的查询结果不会发生变化,即使其他事务修改了数据库中的数据。在这个隔离级别下,事务读取的数据在事务期间保持不变,即使其他事务修改了这些数据。这可以防止脏读和不可重复读,但是可能会导致“幻读”(读取到不存在的数据,因为另一个事务已经插入了这些数据)。

  • SERIALIZABLE:在这个隔离级别下,事务必须按顺序执行,就像它们是顺序执行的一样。这可以防止脏读、不可重复读和幻读,但是可能会导致并发性能下降,因为事务必须按顺序执行。

事务的应用场景 

事务通常用于需要执行多个数据库操作的情况,例如转账操作。如果转账操作不是一个事务,则可能会发生以下情况:

  • 如果第一个账户的余额被减少,而第二个账户的余额没有相应地增加,则可能会导致数据库不一致。

  • 如果第一个账户的余额被减少,但是第二个账户的余额没有相应地增加,并且在此期间系统崩溃,则可能会导致数据丢失。

  • 如果两个用户同时尝试转账,则可能会导致并发冲突。

使用事务可以解决这些问题,因为事务提供了原子性、一致性、隔离性和持久性。如果一个事务的一部分操作失败,则整个事务将被回滚,以确保数据库的一致性。此外,事务可以防止并发问题,并确保数据的持久性,即使系统崩溃。

总结 

事务是MySQL中非常重要的一个概念,它确保了操作的原子性、一致性、隔离性和持久性。在开发Web应用程序时,使用事务可以避免数据不一致的情况发生。MySQL中的事务可以使用START TRANSACTION,COMMIT和ROLLBACK语句来定义和管理。在MySQL中,默认情况下使用InnoDB存储引擎支持事务,而MyISAM存储引擎则不支持事务。

在MySQL中,事务可以使用ACID原则来描述事务的特性。ACID原则是指:

  • 原子性(Atomicity):一个事务中的所有操作要么全部成功,要么全部失败。如果一个事务的一部分操作失败,则整个事务将被回滚,以确保数据库的一致性。

  • 一致性(Consistency):事务执行的结果必须使数据库从一个一致的状态转移到另一个一致的状态。这意味着事务必须遵循数据库中定义的约束和规则,例如键值关系和完整性约束。

  • 隔离性(Isolation):事务应该被隔离,以防止并发问题,例如脏读、不可重复读和幻读。隔离级别定义了事务之间的可见性和影响范围。

  • 持久性(Durability):一旦事务提交,它对数据库所做的更改应该是永久的,即使系统崩溃或重启也是如此。这可以通过将事务更改写入磁盘或其他持久存储器来实现。

MySQL支持这些ACID特性,并允许您选择不同的隔离级别来控制事务之间的并发访问和数据修改。在设计和实现数据库应用程序时,考虑这些原则可以帮助您确保数据的完整性和一致性,以及应用程序的可靠性和可维护性。

总之,ACID原则是保证数据库事务正确执行的基本准则。理解事务的隔离级别和ACID原则可以帮助我们在开发和维护数据库应用程序时避免并发问题,并确保数据的一致性和可靠性。

以上是关于深入了解MySQL的事务ACID原则的主要内容,如果未能解决你的问题,请参考以下文章

深入学习MySQL事务:ACID特性的实现原理

深入学习MySQL事务:ACID特性的实现原理

深入学习MySQL事务:ACID特性的实现原理

MySQL - 深入理解 MySQL 的事务和隔离级别

深入学习MySQL事务:ACID特性的实现原理

Mysql事务并发问题与隔离级别深入解析