修改数据——事务

事务的作用

当执行一组DML操作时,为了确保数据的一致性,避免数据库产生错误数据,就需要通过事务(Transaction)使该组DML操作同时成功或失败。

例如:张三有两张银行卡,卡号分别是1234567890和0987654321,现从1234567890卡取出100块钱转到0987654321卡,则取出钱的卡需要减去100,转入卡需要增加100,现实生活中这两个update操作必须同时成功同时失败,如下操作:
先创建一个表,并添加如下数据

create table account(
  id char(36) primary key,
  card_id varchar(20) unique,
  name varchar(8) not null,
  money float(10,2) default 0
);

insert into account values('6ab71673-9502-44ba-8db0-7f625f17a67d','1234567890','张三',1000);
insert into account (id,card_id,name) values('9883a53d-9127-4a9a-bdcb-96cf87afe831','0987654321','张三’);

特别提示:在每次执行下述SQL语句之前都将数据恢复到初始状态。

操作如下数据
–要求update操作同时成功同时失败才可以实现转账成功。

update account set money=money-100 where card_id= '1234567890';
update account set money=money+100 where card_id= '0987654321';

在这里插入图片描述
如果出现SQL语句错误,如下代码

update account set money=money-100 where card_id= '1234567890';
update account set money=moey+100 where card_id= '0987654321';

在这里插入图片描述
根据输出结果我们可以知道,两条SQL语句并没有同时成功,所以转账未成功,但钱总数少了,即结果已经存到了磁盘当中,这显然不符合我们转账逻辑。这时候我们需要事务来避免这种情况。

开启事务

执行如下SQL语句

set autocommit=0;		//开启事务
update account set money=money-100 where card_id= '1234567890';
update account set money=mon+100 where card_id= '0987654321';

开启事务之后,SQL语句执行完成后,将结果先存到临时内存中,因为没有关闭事务,磁盘中数据还没有变。
临时内存中执行结果为
在这里插入图片描述
磁盘中的结果为(此结果需要开启另一个窗口,再执行查询语句可得到)
在这里插入图片描述

关闭事务

commit

commit:提交事务,将结果持久化到磁盘。

set autocommit=0;	//开启事务
update account set money=money-100 where card_id= '1234567890';
update account set money=money+100 where card_id= '0987654321';	#语句错误
commit;

在这里插入图片描述
在数据库中执行语句时,如果SQL语句出错,用commit提交事务后,依然是将结果持久化到了磁盘,此时得到的数据不严密,我们需要捕获异常。

set autocommit=0;	//开启事务
update account set money=money-100 where card_id= '1234567890';
update account set money=mon+100 where card_id= '0987654321';	#语句错误
commit;

在这里插入图片描述

rollback

rollback:回滚事务,将DML语句执行结果撤销。
执行如下SQL语句

set autocommit=0;
update account set money=money-100 where card_id= '1234567890';
update account set money=mon+100 where card_id= '0987654321';
rollback;

在没有执行rollback之前,内存中数据为
在这里插入图片描述
执行回滚语句之后,内存中数据为
在这里插入图片描述
因为开启事务了,所以不执行rollback之前,没有结束事务,磁盘中数据没有变,在执行了rollback之后,因为操作失败,相当于执行结果被撤销了,所以磁盘中数据依旧是初始值。

其他方法

1,执行了DDL语句(如建表语句)或DCL语句(如给用户授权),如下:

create table user_info(
       id char(36) primary key
)

2,数据库客户端程序退出或数据库崩溃时,为了保持数据一致性,也会结束事务。

注意:

在事务结束之前的所有SQL语句都是处在同一个事务中。
如下特殊情况:

1,开启事务后,执行一条语句,

set autocommit=0;
update account set money=money-100 where card_id= '1234567890';	#锁定语句

再到另一个窗口执行删除语句

delete from account where card_id= '1234567890';	#上边没有关闭事务,会一直等待事务中的上一个语句执行完成。

会出现等待上一个语句关闭情况,会一直等待,如果关闭开启的事务,两个语句都会执行。

rollback;	#关闭后,会删除成功。

总结:

执行DML语句且没有结束事务时,如果需要查询数据库的真实改变情况,则要求在一个新的SQL Window窗口中执行查询语句:因为事务中所做的每一个操作在事务被提交之前都是临时的,在commit或rollback语句执行之前,DML语句首先影响该用户的数据库缓冲区,因为这些操作可以被恢复,而且因为是在该用户的数据缓冲区,所以在原SQL窗口中查询得到的是数据缓冲区的结果,不是数据库真实的数据;要想拿到数据库真实的数据,需要在新SQL窗口中执行查询语句,这样针对不同的用户,MySQL服务器用读一致性来确保每个用户看到的数据和上次提交时的数据相同。

2,在同一个窗口进行两条SQL语句

set autocommit=0;
update account set money=money-100 where card_id= '1234567890';
delete from account where card_id= '0987654321';	#没有关闭事务,在同一个窗口执行俩条语句,相当于两个语句在同一个事务中,都会执行成功。

commit;	#执行成功,而且将结果提交,持久化到磁盘。

总结:

当一个用户执行DML语句时,如果其事物没有结束,则受影响的行被锁定,此时其它用户不能改变受影响行中的数据,后面用户所执行的DML语句会一直处于执行状态,直至前一个用户所执行DML语句事务结束

事务的特性

事务四大特性(ACID):
1,原子性(Atomicity):原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务操作如果成功就完全应用到数据库,否则不会对数据库有任何影响。
2,一致性(Consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态,即一个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还是5000,这就是事务的一致性。
3,隔离性(Isolation):当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离,即对于任意两个并发事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
4,持久性(Durability):一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值