1、概述
事务是数据库区别于文件系统的重要特性之一,有了事务就会让数据库始终保持一致性。
可以通过事务的机制恢复到某个时间点
- 存储引擎是否支持事务,通过执行
show engines;
powershell
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.53 sec)
-
事务的ACID原则
- 原子性(Atomicity)
- 指事务是一个不可分割的工作单位,要么全部提交,要么全部回滚
- 一致性(Consistency)
- 一致性保证事务在执行前后数据库从一个一致状态转移到另一个一致状态。
- 事务在执行过程中必须遵守数据库的约束和规则,如实体完整性、参照完整性等
- 如果事务违反了数据库的约束,那么事务必须被回滚,数据库应该恢复到执行事务前的状态。
- 隔离性(Isolation)
- 隔离性确保在并发执行的多个事务之间,每个事务的操作都不会对其他事务产生影响,即每个事务都似乎是在独立的环境中执行的。
- 可以避免并发执行时的各种问题,如脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)等。
- 持久性(Durability)
- 持久性确保一旦事务提交,其所做的改变将永久保存在数据库中,即使系统发生故障或重启,也不会丢失。
- 数据库管理系统必须能够将已提交的事务的更改持久地保存在稳定的存储介质中,如磁盘或固态硬盘。
- 原子性(Atomicity)
-
事务的状态
- 活动的(active):事务对应的数据库操作正在执行过程中时,事务处于活动的状态。
- 部分提交的:当事务中的最后一个操作执行完成,但由于操作都在内存当中执行,所造成的影响并没有刷新到磁盘时,则该事务处于部分提交的状态。
- 失败的:当事务处在活动的或者部分提交时,可能遇到了某些错误而无法继续执行,或者人为停止当前事务的执行,则该事务处于失败状态
- 中止的:如果事务执行了一部分而变为失败的状态,就需要把已经修改的事务中的操作还原到事务执行前的状态,称为回滚。回滚完毕则事务处于 中止状态
- 提交的:当一个处在 部分提交的 状态的事务将修改的数据都同步到磁盘之后,则该事务处在了提交状态。
2、事务的使用
2.1、显式事务
- 开启事务的方式:
-
方式一:
begin
-
方式二:
start transaction [ read only | read write | with consistent snapshot ]
- read only : 标识当前事务为只读事务
只读事务知识不允许修改那些其他事务也能访问到的表中的数据。对于临时表来说由于只能在会话中可见,所以只读事务可以对临时表进行增删改的
- read write : 标识当前事务是一个读写事务,也就是属于该事务的数据操作既可以读取数据也可以修改数据
- with consistent snapshot : 启动一致性读
-
powershell
#方式一:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
#方式二:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
- 提交或中止事务
- 提交事务(commit):当提交事务后,对数据库的修改是永久性的。
- 回滚事务(rollback):即撤销正在进行的所有没有提交的修改
- 将事务回滚到某个保存点 (rollback to [ savepoint ])
- 在事务中创建保存点,方便后续针对保存点时进行回滚,一个事务中可以有多个保存点:savepoint 保存点名称
- 删除某个保存点: release savepoint 保存点名称
sql
# 提交事务
mysql> commit;
Query OK, 0 rows affected (0.11 sec)
#回滚事务
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
#设置保存点
mysql> savepoint rqtanc;
Query OK, 0 rows affected (0.02 sec)
mysql> select * from rqtanc_test;
+------+------+
| id | name |
+------+------+
| 1 | 12 |
+------+------+
1 row in set (0.27 sec)
mysql> insert into rqtanc_test value(2,'1');
Query OK, 1 row affected (0.25 sec)
mysql> select * from rqtanc_test;
+------+------+
| id | name |
+------+------+
| 1 | 12 |
| 2 | 1 |
+------+------+
2 rows in set (0.00 sec)
# 回滚到设置保存点
mysql> rollback to savepoint rqtanc;
Query OK, 0 rows affected (0.17 sec)
mysql> select * from rqtanc_test;
+------+------+
| id | name |
+------+------+
| 1 | 12 |
+------+------+
1 row in set (0.00 sec)
2.2、隐式事务
- 关键字 :
autocommit
sql
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
3、事务的隔离级别
- 查看数据库隔离级别:
transaction_isolation
;
sql
mysql> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.19 sec)
- 设置事务的隔离级别
sql
#方式一:
SET [ GLOBAL | SESSION ] TRANSACTION ISOLATION LEVEL [ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE ];
#方式二:
SET [ GLOBAL | SESSION ] TRANSACTION_ISOLATION = [ READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE ];
3.1、数据并发问题
脏写
: 对于两事务session A 、session B,如果session A 修改了 另一个 未提交 事务 session B 修改过的事务,则意味着脏写。 如下所示,当session B事务进行回滚,session A中更新也被回滚。
序号 | session A | session B |
---|---|---|
① | begin | |
② | begin | |
③ | update user set user_name = '张三' where user_id = '1' | |
④ | update user set user_name = '李四' where user_id = '1' | |
⑤ | commit | |
⑥ | rollback |
脏读
: 对于session A、session B ,session A 读取了 已经被 session B 更新 但还 没有被提交 的字段。之后若session B 回滚,session A 读取的 内容就是 临时且无效的。 如下所示:当修改session B 回滚后,session A 中的事务相当于读取到了一个不存在的数据,则称为 脏读。
序号 | session A | session B |
---|---|---|
① | begin | |
② | begin | |
③ | update user set user_name = '张三' where user_id = '1' | |
④ | select * from user where user_id = '1';如果读取到的user_name数据为张三,则意味着发生脏读 | |
⑤ | commit | |
⑥ | rollback |
不可重复读
:对于 session A、session B,session A 读取 了一个字段,然后session B 更新了该字段,之后session A 再次读取同一个字段,值不同了 。则发生了 不可重复读。
序号 | session A | session B |
---|---|---|
① | begin | |
② | select * from user where user_id = '1'; (此时user_name 为王五) | |
③ | update user set user_name = '张三' where user_id = '1' | |
④ | select * from user where user_id = '1'; (如果 user_name 的值 为 张三,则意味着发生 不可重复读) | |
⑤ | update user set user_name = '李四' where user_id = '1' | |
⑥ | select * from user where user_id = '1'; (如果 user_name 的值 为 李四,则意味着发生 不可重复读) |
幻读
: 对于两个事务 session A 、session B ,session A 从表中读取一个字段,然后session B 在该表中插入新的行。之后如果session A 再次读取 同一个表,就会多出几行。则意味着发生 幻读。
序号 | session A | session B |
---|---|---|
① | begin | |
② | select * from user where user_id >0; (此时user_name 为王五) | |
③ | insert into user value ('2','张三'); | |
④ | select * from user where user_id > 0 ; (此时user_name 为王五和张三的记录,则意味着发生 幻读) |
3.2、四种隔离级别
READ UNCOMMITTED (读未提交)
:最低的隔离级别,允许读取未提交的数据(脏读)。会有脏读、不可重复读和幻读问题。READ COMMITTED (读已提交)
:仅读取已经提交的数据,防止脏读。但仍然存在不可重复读和幻读问题。REPEATABLE READ (可重复读)
:默认隔离级别,确保同一个事务中的读取操作是可重复的。防止脏读和不可重复读,但可能会有幻读问题。SERIALIZABLE(可串行化)
:最高的隔离级别,完全锁定读取的每一行,防止脏读、不可重复读和幻读。并发性最低。
隔离级别 | 脏读可能性 | 不可重复度可能性 | 幻读可能性 | 加锁读 |
---|---|---|---|---|
READ UNCOMMITTED | √ | √ | √ | × |
READ COMMITTED | × | √ | √ | × |
REPEATABLE READ | × | × | √ | × |
SERIALIZABLE | × | × | × | √ |