一、数据库事务概述
1.1、存储引擎支持事务的情况
show engines;
我们从图中可以看出来目前只有InnoDB支持事务!
1.2、事务的基本概念
数据库事务是指一系列数据库操作的逻辑单元,这些操作要么全部成功执行,要么全部回滚。它的目的是确保数据的一致性和完整性。
⽐如,我们去银⾏转账,操作可以分为下⾯两个环节:
- 从第⼀个账户划出款项。
- 将款项存⼊第⼆个账户。
在这个过程中,两个环节是关联的。第⼀个账户划出款项必须保证正确的存⼊第⼆个账户,如果第⼆个 环节没有完成,整个的过程都应该取消,否则就会发⽣丢失款项的问题。整个交易过程,可以看作是⼀ 个事务,成功则全部成功,失败则需要全部撤消,这样可以避免当操作的中间环节出现问题时,产⽣数 据不⼀致的问题。
**事务:**一组逻辑操作单元,使数据从一种状态变换到另一种状态。
**事务处理的原则:**保证所有事务都作为一个工作单元来执行
,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交( commit
),那么这些修改就永久
地保存下来;要么数据库管理系统将放弃
所作的所有修改
,整个事务回滚( rollback )
到最初状态。
1.3、事务的ACID
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)
一致性(consistency)
隔离性(isolation)
持久性(durability)
1.3.1、原子性(atomicity)
一个事务必须被视为一个不可分割的最小单元,整个事务中的所有操作要么全部提交成功,要么全部失败,对于一个事务来说,不能只执行其中的一部分操作。比如:
连老师借给李老师1000元:
1.连老师工资卡扣除1000元
2.李老师工资卡增加1000元
整个事务的操作要么全部成功,要么全部失败,不能出现连老师工资卡扣除,但是李老师工资卡不增加的情况。如果原子性不能保证,就会很自然的出现一致性问题。
1.3.2、一致性(consistency)
一致性是指事务将数据库从一种一致性转换到另外一种一致性状态,在事务开始之前和事务结束之后数据库中数据的完整性没有被破坏。
连老师借给李老师1000元:
1.连老师工资卡扣除1000元
2.李老师工资卡增加1000元
扣除的钱(-500) 与增加的钱(500) 相加应该为0,或者说连老师和李老师的账户的钱加起来,前后应该不变。
1.3.3、持久性(durability)
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,已经提交的修改数据也不会丢失。
持久性是通过事务日志来保证的。日志包括了重做日志和回滚日志。当我们通过事务对数据进行修改的时候,首先会将数据库的变化信息记录到重做日志中,然后再对数据库中对应的行进行修改。这样做的好处是,即使数据库系统崩溃,数据库重启后也能找到没有更新到数据库系统中的重做日志,重新执行,从而使事务具有持久性。
1.3.4.隔离性(isolation)
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
如果隔离性不能保证,会导致什么问题?
连老师借给李老师生活费,借了两次,每次都是1000,连老师的卡里开始有10000,李老师的卡里开始有500,从理论上,借完后,连老师的卡里有8000,李老师的卡里应该有2500。
我们将连老师向李老师同时进行的两次转账操作分别称为T1和T2,在现实世界中T1和T2是应该没有关系的,可以先执行完T1,再执行T2,或者先执行完T2,再执行T1,结果都是一样的。但是很不幸,真实的数据库中T1和T2的操作可能交替执行的,执行顺序就有可能是:
如果按照上图中的执行顺序来进行两次转账的话,最终我们看到,连老师的账户里还剩9000元钱,相当于只扣了1000元钱,但是李老师的账户里却成了2500元钱,多了10000元,这银行岂不是要亏死了?
所以对于现实世界中状态转换对应的某些数据库操作来说,不仅要保证这些操作以原子性的方式执行完成,而且要保证其它的状态转换不会影响到本次状态转换,这个规则被称之为隔离性。
二、如何使用事务
使用事务有两种方式,分别为显式事务和隐式事务。
2.1、显示事务
步骤1: START TRANSACTION 或者 BEGIN ,作用是显式开启一个事务。
BEGIN;
START TRANSACTION;
START TRANSACTION 语句相较于BEGIN 特别之处在于,后边能跟随几个修饰符:
① READ ONLY :标识当前事务是一个只读事务,也就是属于该事务的数据库操作只能读取数据,而不能修改数据。
② READ WRITE :标识当前事务是一个读写事务,也就是属于该事务的数据库操作既可以读取数据,也可以修改数据。
③ WITH CONSISTENT SNAPSHOT :启动一致性读。
**步骤2:**一系列事务中的操作(主要是DML,不含DDL)
**步骤3:**提交事务 或 中止事务(即回滚事务)
# 提交事务。当提交事务后,对数据库的修改是永久性的。
COMMIT;
# 回滚事务。即撤销正在进行的所有没有提交的修改
ROLLBACK;
# 将事务回滚到某个保存点。
ROLLBACK TO [SAVEPOINT]
情景演示环境准备:
假设我们有一个电子商务应用,其中有 users
、products
和 orders
三张表。
CREATE DATABASE ecommerce;
USE ecommerce;
CREATE TABLE users
(
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
balance DECIMAL(10, 2) NOT NULL DEFAULT 0.00
);
CREATE TABLE products
(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL
);
CREATE TABLE orders
(
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
product_id INT,
quantity INT NOT NULL,
total_price DECIMAL(10, 2) NOT NULL,
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (product_id) REFERENCES products (id)
);