mysql事务

一、什么是事务
1.1 事务的介绍
事务是一个机制,一个操作序列,直白点说就是一组或一条数据库的操作命令(SQL语句)。

把所有的命令作为一个整体向系统提交或者撤销的操作,要么都成功,要么都失败(回滚到提交前的状态)。

事务是一个不可分割的工作逻辑单元,在数据库上执行并发操作时,事务是最小的控制单元。

数据库通过事务的控制和事务的整体性保持数据的一致性。

1.2 事务的特性:ACID
在数据库的管理系统中,事务的特性有ACID这四种:

A :Atomicity :原子性
C :Consistency :一致性
I :Isolation :隔离性
D :Durability :持久性
ACID的具体解释:

原子性 :事务是最小的控制单元,不可分割。事务中的所有操作要么全部完成,要么全部不完成。如果事务中任何一个操作失败,整个事务将被回滚(Rollback)到最初状态,所有的操作都不会生效。
一致性 :事务开始之前和事务结束之后,数据的完整性没有被破坏。开始的时候数据时一致的,结束的时候数据也是一致的。这意味着事务执行后,数据库从一个一致性状态转移到另一个一致性状态。在事务进行的时候,数据可以处于不一致的状态,但是一旦事务结束,数据必须回到一致性。
隔离性 :事务的执行不受其他事务的干扰。即使在并发执行环境下,一个事务的执行也不会受其他事务的影响。不同的事务同时操作相同的数据时,每个事务都有自己完整的数据空间——对数据的修改所发生的并发事务是隔离的。这可以通过各种隔离级别来控制。
持久性 :一旦事务提交,它对数据库的改变是永久性的,即使系统崩溃,数据库也能够通过日志文件进行恢复,保证数据的持久性。
1.3 数据库的隔离级别
未提交读:Read Uncommitted ,RU
允许脏读,即一个事务可以看到其他事务未提交的修改。
提交读:Read Committed ,RC
一个事务只能看到其他事务已经提交的修改,未提交的修改不可见,防止脏读。如oracle和sql server 都是RC。
可重复读:Repeatable Read , RR
一个事务在执行中,执行两次相同的select语句,得到的结果都是相同的。RR是MySQL的默认隔离选项,防止脏读和不可重复读。
串行读:Serializable
相当于锁表,完全串行化的读,一个事务在使用,其他事务的读写都会阻塞。即不能并发读取数据。
1.4 非可重复读的级别下可能出现的情景
一般可重复度(RR)隔离级别的数据库不会出现以下奇葩的情景,但是在非可重复读的隔离级别下,可能会有一些出乎意料的情景,在**提交读(RC)**级别下尤甚。

1.脏读
一个事务可以看到其他事务未提交的修改。这是在RU级别下。

show global variables like '%isolation';
show session variables like '%isolation';
set global transaction isolation level Read Uncommitted;
#设置全局隔离级别RU,可以看到脏读
#全局生效,影响新开的会话,对当前会话不生效
set session transaction isolation level Read Uncommitted;
#对当前会话生效,立即生效

修改隔离级别只要修改isolation level 后面的级别即可。

2.不可重复读
在一个事务内,多次读同一数据,一个事务没有结束,另外一个事务也访问该数据(对数据进行了修改),前一个事务读取的结果不一致。

3.不可更新
两个事务同时对数据进行修改,但是一方先提交,一方后提交,后提交的会覆盖先提交的。

4.幻读
一个事务对一个表的数据进行了修改,另一个事务也修改了表中的数据,前一个事务的修改被后一个事务的修改覆盖了,导致前一个事务发现自己的修改消失了,像出现了幻觉。

2/3/4的情况在**提交读(RC)**级别下完全可能出现,万一碰到了需要注意甄别。

二、事务的控制语句
开启一个事务:

begin;
start transcation;
#两个都可以实现开启事务

提交事务:

commit;
#提交后当前事务结束

一个最简单的开启和提交事务范例:

create table cost (
    id int(4),
	customer char(4),
    money int(6)
);
insert into cost values
(2,'孙二',10),
(3,'张三',100);

mysql> begin;
#开启事务
mysql> select * from cost;
+------+----------+-------+
| id   | customer | money |
+------+----------+-------+
|    2 | 孙二     |    10 |
|    3 | 张三     |   100 |
+------+----------+-------+
mysql> update cost set money=money+1 where id=2;
mysql> select * from cost;
+------+----------+-------+
| id   | customer | money |
+------+----------+-------+
|    2 | 孙二     |    11 |
|    3 | 张三     |   100 |
+------+----------+-------+
mysql> commit;
#提交事务

提交事务后,修改写入数据库中,此时再次运行select * from cost;会得到修改后的结果。如果只是修改而没有提交,重启数据库后,查表会发现修改没有写入数据库,表的值还是一开始的值。(即张三的money=10)

设置回滚点:(类似于设置快照)

savepoint s1;
#设置回滚点s1,s1是自定义的回滚点名称
#回滚点可以创建多个

回滚:(类似于读取快照)

rollback to savepoint s1;
#回滚到回滚点s1的状态

回滚的注意事项:

已提交的事务无法被回滚,事务提交后,事务内的回滚点自动失效
回滚到某一个回滚点后,在这个回滚点之后创建的回滚点都会失效
**不指定回滚点时,默认行为是回滚整个当前的事务。**这意味着,MySQL 将会撤销自上次 BEGIN 或 START TRANSACTION 开始以来所有未提交的更改。

create table cost (
    id int(4),
	customer char(4),
    money int(6)
);
insert into cost values
(1,'丁一',1),
(2,'孙二',10),
(3,'张三',100),
(4,'李四',1000),
(5,'王五',10000);

begin;
update cost set money=money+1 where id=1;
savepoint s1;
update cost set money=money+1 where id=2;
savepoint s2;
update cost set money=money+1 where id=3;
savepoint s3;
update cost set money=money+1 where id=4;
savepoint s4;
update cost set money=money+1 where id=5;

rollback;
rollback to savepoint s1;
rollback to savepoint s2;
rollback to savepoint s3;
rollback to savepoint s4;
select * from cost;
commit;

在update cost set money=money+1 where id=5;之后:

可以先回滚到s4,还可以再回滚到s3,再回滚到s2,再回滚到s1;

但如果直接回滚到s2,则不能再回滚到s3,s4,因为这两个回滚点在s2之后,已经在回滚的过程中消失了,但还可以回滚到s1,;

如果直接rollback,则所有事务的改动全部消失,表变为一开始的状态。

如果直接commit,则不能再回滚。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值