目录
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或者撤销操作请求,即这些操作要么同时成功,要么同时失败。其主要作用就是为了保证数据的统一性和完整性。
最典型的案例:当处理银行账户的转账操作时,可以使用事务来确保数据的一致性和完整性。假设有两个账户,账户A和账户B,我们想要从账户A向账户B转移一定金额。这时候的增加B账户的金额和减少A账户的金额就必须要同时成功,否则就会出现意外情况。
总结:当我们需要同时执行好几个sql语句,并且必须要确保所有的sql语句都运行成功,这时候才会修改数据库中的数据,否则当初临时修改的数据会执行回滚操作将修改的数据恢复回原来的数据。
创建一个账户表并且插入需要用到的数据
- create table account(
- id int auto_increment primary key ,
- name varchar(10),
- money int
- ) comment '账户表';
-
- insert into account (id, name, money) values (null,'zs',2000),(null,'ls',2000);
转账执行流程
查询被转账的账户余额----->被转账用户余额减少------>收入用户余额增加
没有采用事务时的执行基本执行流程
- # 查询用户余额
- select * from account where name = 'zs';
- # 将 zs 的余额减少1000
- update account set money = money - 1000 where name = 'zs';
- # 将 ls 的余额增加1000
- update account set money = money + 1000 where name= 'ls';
执行结果
现在这个执行结果是正确的
现在假设出现了异常情况
- # 查询用户余额
- select * from account where name = 'zs';
- # 将 zs 的余额减少1000
- update account set money = money - 1000 where name = 'zs';
- 出现错误 #语法错误
- # 将 ls 的余额增加1000
- update account set money = money + 1000 where name= 'ls';
这三句sql出现了明显的语法错误,第三句sql是无法执行的,因为前面已经出现了报错
这时候执行结果就会出现钱不见的问题,此时就需要结合事务来完成这个转账功能。
mysql语句中每一句sql语句都是一个独立的事务,且它们都是自动执行的
此时我们可以手动的关闭事务自动提交,改为手动提交
- select @@autocommit; # 查询提交方式,0为手动,1为自动
- set @@autocommit = 0; # 修改提交方式为手动
这时候修改了事务提交的方式,此时在执行对应的sql语句就需要手动提交才可以修改数据
可以看到在我们执行完上面的三句sql后数据并没有修改
手动提交事务
commit;
执行完这条手动提交之后,数据库的数据就发生了变化
假如事务出现了异常,就再手动回滚数据
rollback;
- # 开启事务
- start transaction ;
其实现方式和修改事务的执行方式是一致的
执行完sql后数据不会发生改变,需要手动的提交事务,或者出现异常回滚事务
执行语句也是一样
- commit; # 提交事务
-
- rollback; # 回滚事务
注意这里的提交以及回滚在开启的一个事务中只有一个能执行,假如已经提交了事务,代表此事务已经结束了,就不能在执行回滚事务了,但上面的修改事务的执行方式是可以多次执行的。
原子性(Atomicity):事务是原子的,意味着它要么完全执行,要么完全回滚。如果事务中的任何一部分操作失败,整个事务都将被回滚,不会留下部分更改。
一致性(Consistency):事务开始前数据库必须处于一致状态,事务结束后,数据库也必须保持一致状态。这意味着事务应该满足预定义的约束,如唯一性约束、外键关系等。
隔离性(Isolation):多个事务可以同时执行,但它们应该被隔离,以防止互相干扰。数据库系统通常提供了不同的隔离级别,例如读未提交、读已提交、可重复读和串行化,以控制事务之间的可见性和互动。
持久性(Durability):一旦事务提交,对数据库的更改应该永久保存,即使发生系统崩溃或故障。
脏读:在某些隔离级别下,一个事务可能会读取到另一个事务尚未提交的未确认数据,这被称为脏读。如果读取的数据最终被回滚,读取的数据就会变得无效。
不可重复读:在某些隔离级别下,一个事务可能会在同一个事务中的两次读取之间看到不同的数据,这被称为不可重复读。这可能是由于其他事务的修改导致的。
幻读:在某些隔离级别下,一个事务可能会在同一个事务中的两次查询之间看到不同数量的行,这被称为幻读。这是由于其他事务插入或删除行导致的。
读未提交(Read Uncommitted):最低级别,允许一个事务读取其他事务尚未提交的数据。这可能导致脏读、不可重复读和幻读等问题。
读已提交(Read Committed):这是大多数数据库系统的默认隔离级别。在这个级别下,一个事务只能读取已经提交的数据,解决了脏读。但仍然可能发生不可重复读和幻读。
可重复读(Repeatable Read 默认):在这个隔离级别下,一个事务在开始时会创建一个一致性的快照,然后在整个事务期间使用这个快照。这可以防止不可重复读和脏读,但仍然可能发生幻读。MySQL的InnoDB存储引擎默认使用这个隔离级别。
串行化(Serializable):最高级别,确保了最高程度的数据一致性。在这个级别下,事务之间彻底隔离,不会发生脏读、不可重复读或幻读。但是,它通常会导致性能下降,因为它需要更多的锁定和资源。
select @@transaction_isolation;
当前是默认的
set session transaction isolation level 隔离级别;