事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如 SQL,C++ 或 Java)书写的用户程序的执行所引起,并用形如 begin transaction 和 end transaction 语句或函数调用来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。一般用来管理 insert,update,delete 语句。
假如说:老王有 1000,老李有 1000,老王给老李转账 500。但是银行的系统在执行 update money set balance = balance - 500 where name = '老王';
之后报错了,导致 update money set balance = balance + 500 where name = '老李'
。老李没收到转账就问老王,老王说转了,两个人就打起来。事物的存在就是为了避免这种情况的发生。把多条语句作为一个整体进行操作的功能,被称为数据库事务。数据库事务可以确保该事务范围内的所有操作都可以全部成功或者全部失败。如果事务失败,那么效果就和没有执行这些 SQL 一样,不会对数据库数据有任何改动。
一般来说,事务是必须满足 4 个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。 ♞ 原子性:将所有 SQL 作为原子工作单元执行,要么全部执行,要么全部不执行 ♞ 一致性:事务完成后,所有数据的状态都是一致的 ♞ 隔离性:如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离 ♞ 持久性:即事务完成后,对数据库数据的修改被持久化存储
在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT = 0,用来禁止使用当前会话的自动提交。
BEGIN
或 START TRANSACTION
显式地开启一个事务;
COMMIT
或 COMMIT WORK
提交事务,并使已对数据库进行的所有修改成为永久性的;
ROLLBACK
或 ROLLBACK WORK
回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
SAVEPOINT identifier
,SAVEPOINT
允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT
;
RELEASE SAVEPOINT identifier
删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
ROLLBACK TO identifier
把事务回滚到标记点;
SET TRANSACTION
用来设置事务的隔离级别。
☞ 用 BEGIN, ROLLBACK, COMMIT 来实现
begin # 开始一个事务
// TODO···
rollback # 事务回滚
commit # 事务提交
☞ 直接用 SET 来改变 MySQL 的自动提交模式:
# 查看事务提交哦方式
select @@autocommit;
# 禁止自动提交
set autocommit = 0;
# 开启自动提交
set autocommit = 1;
☞ 注意 使用 set autocommit = 0 的时候,之后所有的 SQL 都将做为事务处理,直到使用 commit 确认或 rollback 回滚结束,注意当结束这个事务的同时也开启了个新的事务!用 BEGIN, ROLLBACK, COMMIT 来实现只将当前的作为一个事务!
对于两个并发执行的事务,如果涉及到操作同一条记录的时候,可能会发生问题。因为并发操作会带来数据的不一致性,包括脏读(读到了其他事务没有提交的数据)、不可重复读(同一个事务中,读到了另一个事务 update 的数据)、幻读(同一个事务中,读到了另一个事务 insert 的数据)等。不可重复读和幻读很类似,但是不可重复读针对的是值的不同,幻读指的是数据条数的不同。数据库系统提供了隔离级别来让我们有针对性地选择事务的隔离级别,避免数据不一致的问题。SQL 标准定义了 4 种隔离级别,分别对应可能出现的数据不一致的情况。
隔离级别 | 脏读(Dirty Read) | 不可重复读(Non Repeatable Read) | 幻读(Phantom Read) | 备注 |
---|---|---|---|---|
read uncommitted(读未提交) | √ | √ | √ | |
read committed(读已提交) | - | √ | √ | Oracle 默认 |
repeatable read(可重复读) | - | - | √ | MySQL 默认 |
serializable(串行化) | - | - | - | 可以解决所有问题但是效率极低 |
☞ 隔离级别相关操作
# 查看事务隔离级别
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.06 sec)
# 设置事务隔离级别,read uncommitted 读未提交
mysql> set global transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.05 sec)