????????事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或者撤销操作请求,即:这些操作要么同时成功,要么同时失败。 例如: 张三给李四转账1000块钱,张三银行账户的钱减少1000,而李四银行账户的钱要增加 1000。 这一组操作就必须在一个事务的范围内,要么都成功,要么都失败。
转账(理想情况):
转账这个操作,?需要按照以下三个步骤来完成:
? ? ?(1)查询张三账户余额;
?????(2)?张三减少?1000;
? ? ?(3)?李四 增加1000;
转账(异常情况):
? ? ? ? 异常情况,?也是分为以下这么三步来完成?,?在执行第三步时报错了?,?这样就导致张三减少1000?块钱?,?而李四的金额没变?,?这样就造成了数据的不一致?,?就出现问题了,如下:
解决:
????????为了解决上述的问题,就需要通过数据库的事务来完成,我们只需要在业务逻辑执行之前开启事务,执行完毕后提交事务。如果执行过程中报错,则回滚事务,把数据恢复到事务开始之前的状态,这样就保证了张三和李四账户的钱是正确的了,不会出现一个账户的钱减少了,而另外一个账户的钱却没有增加的情形。
注意事项:
????????默认MySQL的事务是自动提交的,也就是说,当执行完一条?DML?语句时,?MySQL?会立即隐式的提交事务。
原子性( Atomicity ):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
一致性( Consistency ):事务完成时,必须使所有的数据都保持一致状态。
隔离性( Isolation ):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
持久性( Durability ):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
上述就是事务的四大特性,简称 ACID 。
use vhr;
drop table if exists account;
create table account(
id int primary key AUTO_INCREMENT comment 'ID',
name varchar(10) comment '姓名',
money double(10,2) comment '余额'
) comment '账户表';
insert into account(name, money) VALUES ('张三',2000), ('李四',2000);
(1)查看默认的事务提交方式(默认为1,表示自动提交)
select @@autocommit;?(2)修改为手动提交
set @@autocommit = 0;(3)开启事务
start transcation 或者 begin;
(4)提交事务
commit;
(5)回滚事务
rollback;
正常情况:
异常情况:
注意事项:先把张三、李四的账户金额恢复为2000元;
(1)正常执行,提交事务
(2)异常执行,回滚事务
? ? ? ? 生产环境中的数据操作千变万化,尤其是对于双11、双12这种大型的,全名参与的场景,事务并发操作更是数不胜数!这就为事务的并发问题埋下了伏笔,总的来说,MySQL中的事务并发会产生3类问题,即:脏读、不可重复读、虚读(幻读)。
????????一个事务读到了另外一个事务还没有提交的数据。
????????一个事务先后读取同一条记录,但两次读取数据的结果不同,称之为不可重复读。
?
????????一个事务按照相同的条件查询数据,第一次查询时没有查询到,另一个事务执行完insert后,再次查询又查询到了,好像出现了幻影,称之为"虚读(幻读)"。
?
????????为了解决并发事务所引发的各种问题,在数据库中引入了事务隔离级别的功能,主要分为如下几种:
注意事项:事务隔离级别越高,数据越安全,但是性能越低!
(1)查看MySQL默认的事务隔离级别
select @@transaction_isolation;
(2)设置事务的隔离级别
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }