MySQL作为一种广泛使用的关系型数据库管理系统,支持ACID(原子性、一致性、隔离性、持久性)事务特性,为开发者提供了强大的数据操作和控制能力
本文将通过实例详解MySQL事务的使用,帮助读者深入理解并掌握这一关键技能
一、事务的基本概念 事务是由一系列对数据库中数据进行操作的过程组成的逻辑工作单元
这些操作要么全都执行,要么全都不执行,以此确保数据的一致性和完整性
事务的四个关键特性(ACID)如下: 1.原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不执行
事务在执行过程中发生错误,回滚到事务开始前的状态
2.一致性(Consistency):事务执行前后,数据库都必须处于一致性状态
即事务执行的结果必须是使数据库从一个一致性状态转变到另一个一致性状态
3.隔离性(Isolation):并发的事务之间不会相互干扰,一个事务的中间状态对其他事务是不可见的
4.持久性(Durability):一旦事务提交,它对数据库的改变就是永久性的,即使系统崩溃也不会丢失
二、MySQL事务管理 MySQL提供了多种存储引擎,其中InnoDB是支持事务的默认存储引擎
使用InnoDB存储引擎时,可以通过SQL语句显式地管理事务
2.1 启动事务 在MySQL中,可以使用`START TRANSACTION`或`BEGIN`语句来启动一个新的事务
sql START TRANSACTION; -- 或者 BEGIN; 2.2提交事务 使用`COMMIT`语句可以提交当前事务,使所有在事务中的更改永久生效
sql COMMIT; 2.3 回滚事务 如果事务中的操作失败或出现错误,可以使用`ROLLBACK`语句回滚事务,撤销所有在事务中做的更改
sql ROLLBACK; 2.4 设置自动提交 MySQL默认是自动提交模式,即每个独立的SQL语句都被视为一个事务并自动提交
可以通过设置`autocommit`变量来关闭自动提交模式
sql -- 关闭自动提交模式 SET autocommit =0; -- 执行一系列操作 START TRANSACTION; -- SQL操作 --提交事务 COMMIT; -- 重新开启自动提交模式 SET autocommit =1; 三、事务实例详解 以下通过一个具体的实例来展示如何在MySQL中使用事务
假设我们有一个银行账户表`accounts`,结构如下: sql CREATE TABLE accounts( account_id INT PRIMARY KEY, account_name VARCHAR(50), balance DECIMAL(10,2) ); 并向表中插入一些初始数据: sql INSERT INTO accounts(account_id, account_name, balance) VALUES (1, Alice,1000.00), (2, Bob,1000.00); 现在,我们希望通过一个事务实现从Alice的账户向Bob的账户转账100元
3.1转账事务示例 sql -- 关闭自动提交模式 SET autocommit =0; -- 启动事务 START TRANSACTION; -- 从Alice账户扣款 UPDATE accounts SET balance = balance -100 WHERE account_id =1; -- 检查是否扣款成功 IF(SELECT balance FROM accounts WHERE account_id =1) <0 THEN -- 如果Alice账户余额不足,回滚事务 ROLLBACK; ELSE -- 向Bob账户存款 UPDATE accounts SET balance = balance +100 WHERE account_id =2; --提交事务 COMMIT; END IF; -- 重新开启自动提交模式 SET autocommit =1; 注意:上述SQL语句中的IF逻辑判断在标准的MySQL SQL语句中并不直接支持
在实际应用中,通常会在应用程序代码中实现此类逻辑控制
以下是一个使用Python和MySQL Connector的示例: python import mysql.connector from mysql.connector import Error try: 建立数据库连接 connection = mysql.connector.connect( host=localhost, database=test_db, user=root, password=yourpassword ) if connection.is_connected(): cursor = connection.cursor() 关闭自动提交模式 cursor.execute(SET autocommit =0;) 启动事务 cursor.execute(START TRANSACTION;) 从Alice账户扣款 cursor.execute(UPDATE accounts SET balance = balance -100 WHERE account_id =1;) 获取Alice账户余额 cursor.execute(SELECT balance FROM accounts WHERE account_id =1;) alice_balance = cursor.fetchone()【0】 if alice_balance <0: 如果Alice账户余额不足,回滚事务 cursor.execute(ROLLBACK;) print(Transaction rolled back due to insufficient funds.) else: 向Bob账户存款 cursor.execute(UPDATE accounts SET balance = balance +100 WHERE account_id =2;) 提交事务 connection.commit() print(Transaction committed successfully.) except Error as e: print(fError:{e}) if connection.is_connected(): connection.rollback() 出现错误时回滚事务 finally: if connection.is_connected(): cursor.close() connection.close() print(MySQL connection is closed.) 四、事务隔离级别 MySQL支持四种事务隔离级别,通过设置`transaction_isolation`变量可以更改当前会话的隔离级别: 1.READ UNCOMMITTED(读取未提交):允许读取尚未提交的数据变更,可能会导致“脏读”
2.READ COMMITTED(读取已提交):只允许读取已经提交的数据,可以避免“脏读”,但可能会发生“不可重复读”
3.REPEATABLE READ(可重复读):确保在同一个事务中多次读取数据时,数据是一致的,可以避免“脏读”和“不可重复读”,但“幻读”仍有可能发生(InnoDB通过MVCC解决幻读问题)
4.SERIALIZABLE(可串行化):强制事务串行执行,完全避免“脏读”、“不可重复读”和“幻读”,但性能开销最大
sql -- 设置隔离级别为可重复