事务控制语句:
-
BEGIN 或 START TRANSACTION 显式地开启一个事务;
-
COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的;
-
ROLLBACK 也可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
-
SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
-
RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
-
ROLLBACK TO identifier 把事务回滚到标记点;
-
SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。
事务并发下出现的问题
通常事务并发会出现几种现象:1.脏读;2.不可重复读;3.幻读。
- 脏读
一个事务 A
读取了另一个并行事务 B
未最终提交的写数据, 那事务A
的这次读取就是脏读。
- 不可重复读
假设“脏读”问题完全解决了,那就意味着事务中每次读取到的数据都是“持久性”的数据(被别的事务最终“提交/回滚”完成后的数据)。
但是解决了脏读问题, 只是能保证你在事务中每次读到的数据都是持久性的数据而已!
如果在 一个事务 中多次读取同一个数据,正好在两次读取之间,另外一个事务确实已经完成了对该数据的修改并提交,那问题就来了,可能会出现 多次读取结果不一致 的现象,这种现象也就被称为不可重复读:
A事务读取了B事务已经提交的更改(或删除)数据。比如A事务第一次读取数据,然后B事务更改该数据并提交,A事务再次读取数据,两次读取的数据不一样。将数据库事务隔离级别设为repeatable read即可
- 幻读
事务 A
在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务 B
执行了新增数据的操作并提交后,这个时候事务 A
读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,这种现象就称为幻读:
A事务读取了B事务已经提交的新增数据。注意和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。这两种情况对策是不一样的,对于不可重复读,只需要采取行级锁防止该记录数据被更改或删除,然而对于幻读必须加表级锁,防止在这个表中新增一条数据(PS:对于锁的问题请自行查找或关注我的后续文章)。
当然,也可以将数据库事务隔离级别设为serializable,但一般不这样做,因为该策略是完全阻塞的,将对数据库的访问完全序列化,并发性能最差。
如果A事务只进行读操作,不进行写操作,将数据库事务隔离级别设为repeatable read,并用start transaction with consistent snapshot开启事务,同时进行快照读,也可以防止幻读现象(因为在可重读策略下,不是开启事务就建立快照点,而是在第一次查询时建立快照点)
丢失更新
第一类丢失更新:A事务提交时,把已提交的B事务的数据覆盖掉。
第二类丢失更新:A事务回滚时,把已提交的B事务的数据覆盖掉。
第一类
理论库存是7个,但现在剩余8个;
第二类
理论库存是9个,但现在剩余10个;(这是抄的 抄的)