本节是SQL基础篇的最后一章,我们来主要介绍一下SQL语句中的事务。
目录
概述
事务可以想象成一个“打包处理”的操作集合。比如你去银行转账,事务就是把“从A账户扣钱”和“向B账户加钱”这两步操作捆绑在一起。事务内的所有操作要么全部执行成功,要么全部不执行。
注:MySQL默认开启自动提交模式,执行每条DML语句后都会立即隐式提交事务。
举个例子:
我们在ATM机办理业务,具体业务如下:
1.查询余额
2.给张三转500块(即我们账户余额-500,张三账户余额+500)
那么问题就来了,如果在我们余额-500完成后要是在给张三余额+500时候发生异常那么没有事务的话我们的余额就平白扣了500,这显然不合理,这时候就需要事务了。
要是在用户点击了转账按钮后开启事务,那么在抛出异常的时候就会回滚事务,把我们的余额会变成扣除之前的。
具体操作
-- 查询卡号为123456的用户余额
SELECT name,money FROM account WHERE credit_card_number = '123456';
-- 我们的账户余额-500
UPDATE account SET money = money - 500 WHERE credit_card_number = '123456';
异常
-- 张三账户余额+500
UPDATE account SET money = money + 500 WHERE credit_card_number = '114514';
MySQL中的事务是自动提交的所以说每一条都是一个事务。这样就会造成如下效果:
用户名 | 余额 |
---|---|
逻辑非 | 50,000 |
张三 | 40,000 |
用户名 | 余额 |
---|---|
逻辑非 | 49,500 |
张三 | 40,000 |
查看/设置事务提交方式
-- 查看当前是否自动提交,1 表示自动提交模式开启,0 表示关闭
SELECT @@autocommit;
-- 关闭自动提交模式
SET @@autocommit=0;
开启事务
START TRANSACTION 或 BEGIN;
提交事务
COMMIT;
回滚事务
ROLLBACK;
使用示例:
SELECT name,money FROM tb_user;
start TRANSACTION;
UPDATE account SET money=money-500 WHERE credit_card_number='123456';
异常模拟
UPDATE account SET money=money+500 WHERE credit_card_number='114514';
COMMIT;
ROLLBACK;
SELECT name,money FROM tb_user;
这样发生异常后金额还是原来的金额
四大特性(ACID)
1.原子性(Atomicity)
- 事务是一个不可分割的工作单位,要么全部执行成功,要么全部失败回滚。
- 例如:转账操作(A 转 B 100 元),如果 A 扣款成功但 B 未到账,则整个事务回滚,A 的钱不会减少。
2.一致性(Consistency)
- 事务执行前后,数据库必须保持一致性状态(符合业务规则)。
- 例如:转账前后,A 和 B 的账户总额应保持不变(A-100,B+100)。
3.隔离性(Isolation)
- 多个事务并发执行时,一个事务的操作不应影响其他事务。
- 例如:事务 A 读取数据时,事务 B 不能修改该数据(取决于隔离级别)。
4.持久性(Durability)
- 事务一旦提交,其对数据库的修改就是永久性的,即使系统崩溃也不会丢失。
- 例如:转账成功后,即使数据库服务器宕机,数据也不会回滚。
并发事务问题
问题 | 描述 |
---|---|
脏读 | 一个事务读到另外一个事务还没有提交的数据。 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同。 |
幻读 | 一个事务按照条件查询数据时,没有对应的数据行,但在在插入数据时,又发现这条数据已经存在了。 |
事务隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED | √ | √ | √ |
READ COMMITTED(Oracle默认) | × | √ | √ |
REPEATABLE READ(MySQL默认) | × | × | √ |
SERIALIZABLE | × | × | × |
READ UNCOMMITTED:无保障,性能高但风险大
READ COMMITTED:避免脏读
REPEATABLE READ:避免脏读和不可重复读
SERIALIZABLE:完全串行化,性能最低
查看事务隔离级别
SELECT @@transaction_isolation;
设置事务隔离级别
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE];
注:数据隔离级别越高,数据越安全,但性能越低。