Mysql事务实操

1. 什么是Mysql事务


MySQL 的事务(Transaction)是用于确保数据库操作的原子性、一致性、隔离性和持久性(ACID)的机制。事务可以保证一组操作要么全部成功,要么全部失败,从而确保数据的一致性和可靠性。

1.1 事务的特性


  • 原子性 (Atomicity): 事务是一个不可分割的工作单元,事务中的所有操作要么全部完成,要么全部不执行。即使在系统崩溃的情况下,也不会出现部分操作成功,部分操作失败的情况。

  • 一致性 (Consistency): 事务的执行必须使数据库从一个一致的状态转变为另一个一致的状态。在事务开始之前和结束之后,数据库的完整性约束不会被破坏。

  • 隔离性 (Isolation): 多个事务并发执行时,一个事务的执行不会受到其他事务的干扰。不同的事务之间是相互独立的。根据隔离级别的不同,事务可能会看到其他事务的部分或全部操作。

  • 持久性 (Durability): 一旦事务提交,它对数据库的修改就会被永久保存,即使系统崩溃也不会丢失。

1.2 Mysql的事务控制语句


  • 开始事务 (START TRANSACTION): 开始一个新的事务。可以在事务中执行多个SQL操作。

  • 提交 (COMMIT): 提交事务,将事务中的所有操作永久保存到数据库中。

  • 回滚 (ROLLBACK): 回滚事务,撤销事务中的所有操作,使数据库恢复到事务开始之前的状态。

  • 保存点 (SAVEPOINT): 创建一个事务的保存点,允许部分回滚到指定的保存点,而不是回滚整个事务。

1.3 事务的隔离级别


  • 读未提交 (Read Uncommitted): 事务可以读取其他未提交事务的数据,可能导致脏读 (Dirty Read)。

  • 读已提交 (Read Committed): 事务只能读取其他已提交事务的数据,避免了脏读,但可能会出现不可重复读 (Non-repeatable Read)。

  • 可重复读 (Repeatable Read): 在事务开始后,事务内的所有读操作都只能看到事务开始时的状态,防止不可重复读,但可能会出现幻读 (Phantom Read)。

  • 可串行化 (Serializable): 最严格的隔离级别,事务逐个执行,完全避免了脏读、不可重复读和幻读,但效率最低。

1.4 事务的应用场景


事务通常用于需要确保数据一致性的场景,例如:

  • 银行转账:确保从一个账户扣款,同时另一个账户加款。
  • 订单处理:确保订单信息和库存信息的更新是一致的。

1.5 Mysql的InnoDB存储引擎


在 MySQL 中,InnoDB 是一个支持事务的存储引擎,它提供了完整的ACID支持。通过使用InnoDB,MySQL 可以确保事务的可靠性和数据的完整性。

理解 MySQL 的事务机制有助于在实际应用中正确使用事务,确保数据的完整性和一致性。

2. Mysql事务实际操作


下面通过一个简单的例子来演示如何在Mysql中使用事务。

假设有两个表:‘accounts’和’transactions’。'accounts’表用来存储用户的账户余额,而’transactions’表用来存储每次转账的历史记录。

2.1 创建表结构


通过sql语句创建两个表

CREATE TABLE accounts (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_name VARCHAR(50),
    balance DECIMAL(10, 2)
);

CREATE TABLE transactions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    from_account INT,
    to_account INT,
    amount DECIMAL(10, 2),
    transaction_date DATETIME
);

2.2 插入测试数据


接下来,我们插入一些测试数据到 accounts 表中:

INSERT INTO accounts (user_name, balance) VALUES ('Alice', 1000.00);
INSERT INTO accounts (user_name, balance) VALUES ('Bob', 1000.00);

执行完毕之后,数据如下所示:
![[Pasted image 20240815155433.png]]

2.3 使用事务进行转账操作


假设我们要从 Alice 的账户转 200 元到 Bob 的账户。我们需要确保这两个操作要么同时成功,要么同时失败。因此,我们使用事务来处理这次转账。

-- 开始事务
START TRANSACTION;

--Alice 的账户中扣款
UPDATE accounts SET balance = balance - 200 WHERE user_name = 'Alice';

--Bob 的账户中加款
UPDATE accounts SET balance = balance + 200 WHERE user_name = 'Bob';

-- 插入一条转账记录
INSERT INTO transactions (from_account, to_account, amount, transaction_date)
VALUES (
    (SELECT id FROM accounts WHERE user_name = 'Alice'),
    (SELECT id FROM accounts WHERE user_name = 'Bob'),
    200,
    NOW()
);

-- 提交事务
COMMIT;

执行完毕之后的日志如下所示:
![[Pasted image 20240815155609.png]]

2.4 检查结果


事务提交后,我们可以查看账户余额和交易记录是否正确:
如果一切正常,accounts 表中的 Alice 的余额应该减少了 200 元,而 Bob 的余额应该增加了 200 元。同时,transactions 表中应有一条记录,显示从 Alice 到 Bob 的转账信息。
accounts表如下所示:
![[Pasted image 20240815155655.png]]

transactions表如下所示:
![[Pasted image 20240815155727.png]]

事实确实如此。

2.5 模拟事务失败并回滚


现在我们模拟一个事务中的操作失败,并使用 ROLLBACK 来撤销之前的操作。假设我们在扣款后,遇到某种错误,不想继续后续操作。

-- 开始事务
START TRANSACTION;

--Alice 的账户中扣款
UPDATE accounts SET balance = balance - 200 WHERE user_name = 'Alice';

-- 模拟错误(可以通过故意写错 SQL 语句或遇到某种异常)
-- 假设这里的操作失败了
-- 错误:UPDATE accounts SET balance = balance + 200 WHERE user_name = 'Unknown';

-- 回滚事务
ROLLBACK;

回滚后,Alice 的账户余额应该恢复到事务开始前的状态。
此时之前将两个用户的金额都调回了1000。

执行这个事务:
![[Pasted image 20240815160107.png]]

查看结果:
可见事务发生了回滚操作,两者的金额并未发生改变。
![[Pasted image 20240815160123.png]]

3. 总结


这个简单的示例展示了如何在 MySQL 中使用事务来确保数据的一致性和完整性。事务操作在实际项目中非常重要,特别是在涉及到多个表的复杂操作时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值