参考: https://blog.csdn.net/w_linux/article/details/79666086
https://www.runoob.com/mysql/mysql-transaction.html
事务定义
事务(Transaction):一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务。比如A给B转账,那么A转出和B转入这两个在一起才是一个完整的业务,要么同时成功,要么同时失败。
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成
事务原则ACID
原子性(Atomicity):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成
一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏,写入的资料必须完全符合所有的预设规则。
隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)
持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
事务控制语句
-
在 MySQL 命令行的默认设置下,事务都是自动提交的,因此要显式地开启一个事务务须使用命令
BEGIN
或START TRANSACTION
,或者执行命令SET AUTOCOMMIT=0
,用来禁止使用当前会话的自动提交。 -
提交事务:
COMMIT
,使已对数据库进行的所有修改成为永久性的 -
回滚:
ROLLBACK
,结束用户的事务,并撤销正在进行的所有未提交的修改 -
SAVEPOINT 保存点
,允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT; -
RELEASE SAVEPOINT 保存点
删除一个事务的保存点 -
ROLLBACK TO 保存点
把事务回滚到标记点; -
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL <isolation-level>
用来设置事务的隔离级别,其中的<isolation-level>
可以是:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE
四种隔离级别
1、读未提交:read uncommitted
在这种隔离级别下,事务B可以读取到事务A修改过,但是未提交的数据,引发脏读
问题。这是最低的一种隔离级别, 数据库隔离级别一般都高于该级别。
2、读已提交:read committed
事务A提交过后的数据,事务B才可以去读。可以避免脏读,但可能发生不可重复读
问题。不可重复读问题是指,在一个事务内,重复读取某个数据,读到的结果可能不一样,这是因为在读取过程中可能被其他事务进行了修改。
3、可重复读:repeatable read
事务A提交后的数据,事务B仍然是读不到。因此事务B即使多次读,读到的结果仍然一致。可以避免不可重复读问腿,但可能导致幻读
问题。幻读是指在一个事务中,读取到了其他事务插入的数据,导致自己前后读取的数据不一致
4、串行化:serializable
事务A和事务B,事务A在操作数据库时,事务B只能排队等待。这种隔离级别很少使用,吞吐量太低,用户体验差。这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行,而不并发
参考:https://blog.csdn.net/w_linux/article/details/79666086
事务测试
有两个账户A和B,分别存有1000和500元
START事务后,手动提交或者回滚,提交会自动结束事务:
START TRANSACTION; -- 开启一个事务
UPDATE `account` SET `money` = `money`-100 WHERE `name` = 'A';
UPDATE `account` SET `money` = `money`+100 WHERE `name` = 'B';
-- ROLLBACK; -- 回滚
COMMIT; -- 提交
SET关闭自动提交,最后要开启:
SET autocommit = 0; -- 关闭事务自动提交
UPDATE `account` SET `money` = `money`-100 WHERE `name` = 'A';
UPDATE `account` SET `money` = `money`+100 WHERE `name` = 'B';
-- ROLLBACK; -- 回滚
COMMIT; -- 提交
SET autocommit = 1; -- 开启事务自动提交
可以设置保存点,之后回到保存点:
START TRANSACTION; -- 开启一个事务
UPDATE `account` SET `money` = `money`-100 WHERE `name` = 'A';
UPDATE `account` SET `money` = `money`+100 WHERE `name` = 'B';
SAVEPOINT `保存点`
UPDATE `account` SET `money` = `money`-100 WHERE `name` = 'A';
UPDATE `account` SET `money` = `money`+100 WHERE `name` = 'B';
ROLLBACK TO `保存点`; -- 回滚
COMMIT