mysql---事务

什么存储引擎支持事务

1、查看数据库引擎是否支持事务(Innodb支持)?
show engines;
在这里插入图片描述
2、查看MySQL当前默认的存储引擎?
show VARIABLES LIKE ‘%storage_engine%’;
在这里插入图片描述
3、查看某张表的存储引擎?
show create table 表名;
4、对于表的存储结构的修改?
建立Innodb表:Create table 表 type = Innodb;Alter table 表 type=Innodb;

事务的特性

事务应该具有四个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
1、原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸多操作要么都做,要么都不做。
2、一致性(consistency):事务必须是使数据库从一个一致性状态变到另外一个一致性状态。一致性与原子性是密切相关的。
3、隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
4、持久性(durability):也称为永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

原子性的例子:
小明给小红转账1000,
小明的账户就-1000,
小红的账户就+1000。
整个事务要么全部成功,要么全部失败。不可能扣了小明的钱,但不给小红加上,这不合理。

一致性的例子:
小明给小红转账1000,
小明的账户就-1000,
1、小红的账户增加1000,
2、小红的账户增加2000。
小明转账的过程中,发生了卡顿,系统以为没有给小红加上,又加了一次。这样银行就要找小红了。一致性就是小明扣多少,小红就只能加多少,两者相加等于0。

持久性的例子:
并不是数据库的角度完全能解决的。比如热备份、读写分离等。

隔离性级别

未提交读(READ UNCOMMITED) 导致脏读
已提交读(READ COMMITED)导致不可重复读
可重复读(REPEATABLE READ)
可串行话(SERIALIZABLE)

MySQL默认事务隔离级别为repeatable-read。
可通过语句查:show VARIABLES LIKE ‘%isolation%’
在这里插入图片描述

不同隔离性级别在并发环境下的问题

脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。比如小明的账户有5000,操作取钱1000,这时候小红又来取小明的钱,此时账户只有4000。但是小明回滚了账户,账户有5000。实际小红读的数据是脏数据。

不可重复读:事务A多次读取同一个数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一样。比如在同一个事务中,小红第一次查看小明的工资是五千,这时候小明从账户取出了1000块,并提交了自己的事务,这时候小红第二次查看小明的工资的时候变成了4千,导致了在同一个事务中读取同一个数据的值不同。

可重复读:事务A原来账户5000,在自己的事务中减去了1000,事务B去获取账户的时候还是5000,则时候A事务提交。事务B在去获取账户余额的时候还是5000。

幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发送了幻觉一样,就叫幻读。

注意: 不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需要锁住满足条件的行,解决幻读需要锁表(消耗性能)。

不同隔离性级别设置和操作

1、未提交读(READ UNCOMMITED) 脏读
set SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITED;

例子:
一个session中,balance = 450
start TRANSACTION
update account set balance = balance - 50 where id = 1;

另外一个session中查询,balance = 400
select * from account;

回到第一个session中 回滚事务
ROLLBACK

在第二个session中
update account set balance = balance - 50 where id = 1;
查询结果还是400。

2、已提交读(READ COMMITED)不可重复读
set SESSION TRANSACTION ISOLATION LEVEL READ COMMITED;

例子:
一个session中
start TRANSACTION
update account set balance = balance - 50 where id = 1;

另外一个session中查询(数据并没改变)
select * from account;

回到第一个session中提交事务
commit

在第二个session中
select * from account;(数据已改变)

3、可重复读(REPEATABLE READ)
set SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

例子:
一个session中(account=450)
start TRANSACTION
update account set balance = balance - 50 where id = 1;

另外一个session中查询(数据并没改变,account=450)
select * from account;

回到第一个session中提交事务
commit

在第二个session中
select * from account;(数据并未改变,balance=450)

4、可串行化(SERIALIZABLE)
set SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

例子:
开启一个事务
BEGIN
select * from account;
select sum(a.balance) from account a;

在另外一个session中
BEGIN;
insert into account values(2, 1000);
commit;

回到第一个session中
select sum(a.balance) from account a;结果并没变化
提交
select sum(a.balance) from account a;结果并没变化

在这里插入图片描述

总结

事务隔离级别为可重复读时,如果有索引(包括主键索引)的时候,以索引列为条件更新数据,会存在间隙锁间、行锁、页锁的问题,从而锁住一些行;如果没有索引,更新数据时会锁住整张表。

事务隔离级别为串行化时,读写数据都会锁住整张表。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为READ COMMITTED,它能够避免脏读取,而且具有较好的并发性能。

事务的语法

1、开启事务
A、begin
B、start transaction(推荐)
C、begin work

2、事务回滚 rollback

3、事务提交commit

4、还原点savepoint
比如在一个事务中,不想回滚整个事务的时候,可以添加多个还原点,当想回滚部分数据的时候,只需要回滚某个还原点就行了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值