X  
登录

还没有账号?立即注册

忘记密码?
登陆
X  
注册

已经有账号?马上登陆

获取验证码
重新获取(60s)
立即注册
统计
  • 建站日期:2021-03-10
  • 文章总数:518 篇
  • 评论总数:155 条
  • 分类总数:32 个
  • 最后更新:4月20日
文章 mysql语言

数据库事务为什么这么重要?

梦幻书涯
首页 mysql语言 正文

设置事务隔离级别

SHOW VARIABLES LIKE 'transaction_isolation';# 读取变量
SHOW VARIABLES LIKE 'autocommit'; # 读取变量
#读已提交
set session transaction isolation level read committed ;
#读未提交
set session transaction isolation level read uncommitted ;
#可重复度 mysql默认级别
set session transaction isolation level repeatable read  ;
#串行化|序列化
set session transaction isolation level serializable  ;
#------ 开启事务-----
#开启可读写事务 开启事物
start transaction,begin
#开启只读事务
start transaction read only;
#开启读写事务 与start transaction;等价
start transaction read write;

#事务提交
commit;
#事务回滚
rollback;
#------事务挂起-----
#记录事务保存点 mm为保存点自定义的id
savepoint mm;
#回滚事务到mm 保存点.直接运行rollback全部回滚
ROLLBACK TO mm;
#删除保存点
RELEASE SAVEPOINT mm;

SHOW VARIABLES LIKE 'transaction_isolation';

# 开启事务
start transaction ;
# start transaction read only; 只读事务 后续讲解
#事务开启后如果没有执行 commit 那么数据并不会真正写入数据库中,
# 但sql语句会生产临时数据(临时数据后面在引用问题,当然不会扩展到mvvc内容,主要我太菜)。
# 小明给小张转账
update User set money=money-23 where username='小明';
update User set money=money+23 where username='小张';
#提交事务
commit ;
#根据需要回滚
# rollback;

事务概念

# 事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行,因此事务是一个不可分割的工作逻辑单元。

# 事务具有四大性质:

#原子性:不可拆分,所有步奏或流程必须全部执行,不然全部失败,也就是要么全部成功执行,要么全部不执行
#一致性:一致性就是数据的一致性符合业务的逻辑的一致性,例如取款1000  但是卡里余额没减少1000  就不一致了
#隔离性:就是为了解决并发引起的问题,把一些事务隔离开,    在没提交之前,对其他事务是不可见的状态,多个并发的事务之间相互隔离。有四种隔离级别
        读未提交(更新未提交) read uncommitted、# 没解决脏读、幻读、不可重复读、更新丢失
        读已提交(更新已提交) read committed、  # 解决了脏读  其余没
        可重复读 repeatable read              # 解决了脏读、幻读、不可重复读、更新丢失(悲观锁|乐观锁)
        系列化 Serializable   、              # 解决了脏读、幻读、不可重复读、更新丢失
#持久性:就是提交的事务必须永久生效,不会因为断电,系统崩溃等故障而丢失。

并发引起的问题

#多个用户访问相同的数据,因增删改而引起的一系列问题
# 1、脏读  就是一个事务它更新了,但是还没commit提交,另外一个事务就能读取到,例如转账,我转账1000到账号B,账户B读取到钱而取款了,我rollback回滚,导致这个钱没转成功,但是账户B的负责人已经领取到1000元了。

# 2、幻读:针对删除,新增,例如你查询菜单,一开始有5种,后来被其他人新增了2种,你再次读取就会出现7种,就有点错觉,或者你本来查询了5种结果,后来被删除了一种,你在刷新一下再次查询就只剩下四种,就感觉出现幻觉一样。

# 3、不可重复读:你查询Id=2,里面的balance的余额本来1000元,但是你再次查询余额数据又发生了改变,这就是重复读出现不同结果 ,所以叫不可重复读,因为重复读取的结果不一样,所以不可重读。

# 4、更新丢失:例如A充值AAaa账号200,B充值AAaa账号300,AAaa账号里面余额还有一千,无论那个成功结果要么2200  | 2300  本来应该2500的
#            这样就出现丢失数据的

1、这就是脏读

A窗口:
show variables like 'transaction_isolation';
set session transaction isolation level read uncommitted;
begin;
select * from bank_card where id=1;
# 查询余额还有1000元
B窗口:
begin;
update bank_card set balance=2000 where id =1;;
A窗口:
select * from bank_card where id=1;
# 查询余额还有2000元
B窗口:
rollback;
A窗口:
select * from bank_card where id=1;
# 查询余额还有1000

1、这就是不可重复读

A窗口:
show variables like 'transaction_isolation';
set session transaction isolation level read committed;
begin;
select * from bank_card where id=1;
commit;
# 查询余额有1000元
B窗口:
begin;
update bank_card set balance=2000 where id =1;;
commit
A窗口再次查询:
select * from bank_card where id=1;
# 查询余额有2000元,两次读取的数据不一样,对于A来说就有点问题

1、这就是幻读

A窗口:
show variables like 'transaction_isolation';
set session transaction isolation level read committed;
begin;
select * from bank_card where id=1;
commit;
# 查询余额还有1000元
B窗口:
begin;
delete from bank_card where id=1;
commit;
A窗口:
begin;
select * from bank_card where id=1;
commit;
# empty 该记录不存在  对于A来说 第一次能读到数据,刷新一下就错了 就感觉出现幻觉一样

1、这就是更新丢失

A窗口:
show variables like 'transaction_isolation';
set session transaction isolation level read committed;
begin;
update bank_card set balance=2000+200 where id =1;;
commit;
# 查询余额还有1000元
B窗口:
begin;
update bank_card set balance=2000+300 where id =1;
A窗口:
select * from bank_card where id=1;
# 查询余额还有2200元 | 2300元 本来是2500,或者对于A来说应该是看到2200的 这样就存在数据丢失

# 这个就需要用到悲观锁和乐观锁

为何可重复读 Repeatable Read+序列化 Serializable 能够解决更新丢失 和幻读和不可重复读

可重复读 Repeatable Read:
    # 更新丢失用到:悲观锁和乐观锁解决
    # 幻读和不可重读,是因为用到快照的概念或者MVCC多版本并发的概念
    就是当A开启了事务,只要不提交,及时B更新了数据,或者删除了数据,
    在A还没提交事务情况下,A都能查询到该数据,而且数据也不是B修改后的。
    当A提交了事务,那么A再次查询可能是B修改的数据或者已经被B删除了。
序列化 Serializable  
    # 想象只有我一个人在用,例如我开启了事务,begin,其他人增删改都是不能操作的,必须等我提交了这个事务,其他人才能执行他们的增删改
    这个对性能影响很大,因为没支持并发。

幻读和不可重复读的区别

#幻读和不可重复读:
       #幻读针对的是一系列记录数量或标题发生改变

       #不可重复读针对的是一条记录里面的数据内容发生改变

悲观锁和乐观锁

#查询语句里面新增一个版本好或其他判断标志
-- 乐观锁
#本来num=1,你一更新它就变成2,那么另外一个即使语句一模一样,也找不到num=1的结果,故他无法更新数据,这就是乐观锁
update bank_card set balance=balance+200 ,num=num+1 where id=3 and num=1; 

-- 悲观锁
begin;
select * from bank_card where id =3 for update; 

-- 谁事务开启在前,谁就先占用了线程,只要等这个人提交事务commit,其他人才能执行其他业务。

-- 这两个解决了更新丢失问题

版权说明
文章采用: 《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权。
版权声明:未标注转载均为本站原创,转载时请以链接形式注明文章出处。如有侵权、不妥之处,请联系站长删除。敬请谅解!

-- 展开阅读全文 --
这篇文章最后更新于2022-5-29,已超过 1 年没有更新,如果文章内容或图片资源失效,请留言反馈,我们会及时处理,谢谢!
mysql8一些重点函数的运用
« 上一篇
进程,单线程,多线程的区别和联系
下一篇 »

发表评论

HI ! 请登录
注册会员,享受下载全站资源特权。
登陆 注册
永远的少年,永远的梦

热门文章