为什么别人改的你看不到?

可能看到标题很多人比较懵,其实我们这章主要要说的就是事务的机制,那在开始之前一个思考题,什么隔离级别下别人改的你会看不到呢?

事务是什么

说到事务,只要是一个合格的JAVA程序员其实应该都不陌生,比如现在场景如下:
小明有一百块钱,要去银行存起来,这个时候小张向小明又转了一百元钱,那么这个时候就会涉及到事务了,那么里面转入的时候小明是不是立即就能查到呢,这个就要看隔离性了。

其实事务就是保证数据库的一组操作,要么全部成功,要么全部失败。mysql中事务主要是在引擎层实现的,这也就会导致mysql不一定在所有情况下都会支持事务,比如inoodb支持事务,myisam就不支持。

事务隔离级别

事务四大特性

ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)

事务存在的问题

事务存在脏读,幻读,不可重复读的问题

脏读:在A事务未处理结束,B事务就可以读到相应的更改;
在这里插入图片描述

幻读:幻读就是说我开启一个A事务,在第一次读取的时候无法读到,这个时候B事务将对应数据插入,但是A事务并读不到当前插入的数据,所以自己进行对应数据插入,此时就会报错重复数据(RR级别下)
在这里插入图片描述

不可重复读:不可重复读指的就是事务A在事务B读取数据过程中对数据多次更改,导致每次的数据都不一致
在这里插入图片描述

事务几种隔离级别

事务隔离级别主要有以下几种:read-committed(读提交),read-uncommitted(读未提交),repeated-read(可重复读),serializable(串行化)
在这里插入图片描述

读提交:可以解决脏读的问题,上图中V1的值为1,v2,v3值均为2

读未提交:不能解决任何问题,上图中v1,v2,v3均为1

可重复读:可以解决不可重复读,脏读的问题,上图中v1,v2均为1,v3为2

串行化:串行化能够解决所有问题,但是类似于串行处理,所以性能不高

其实事务其中有个很重要的概念就是MVCC视图。其中RC级别下没有视图概念,直接返回最小数据行;RU级别下会在每个语句之前都创建一个MVCC视图;RR级别下会在每一次事务开启之前创建MVCC视图;serial级别下会通过锁来实现数据读取,所以保证数据安全。

隔离级别的查看修改

mysql> show variables like 'transaction_isolation';

+-----------------------+----------------+

| Variable_name | Value |

+-----------------------+----------------+

| transaction_isolation | READ-COMMITTED |

+-----------------------+----------------+

修改的话只需要设置translaction_isolation的值即可。

事务隔离级别的实现
当前读和快照读

当前读:比如增加了排他锁,共享锁这种能够获取到最近数据的操作都叫当前读;

快照读:像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行圾别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本。

read-review实现的回滚

其实我们的MVCC中有几个关键字段,read-review,undolog以及隐式字段。
在这里插入图片描述

如果一条变更语句,那么会将变更记录操作记入redolog中,将回滚操作计入undolog中。

正如图所示,如果我们需要回滚就依次执行所有回滚操作就可以,那么什么时候read-review会被删除。其实是在不再被使用的时候,没有其他事务使用当前的undolog的时候,purge线程就会对其回收。所以长事务是不建议的,因为长事务会导致日志无法被回收,导致系统占用的磁盘会越来越多。除了会有很多回滚段的问题,长事务还会占用锁资源,最后拖垮整个库。

事务启动方式

显式启动事务,即使用start和begin translation启动事务,一定要将set autocommit设置为1,因为设置为0的话是不支持自动回滚和提交的,所以会出现意外的长事务,当然基本都是代码造成的。
如果需要查询长事务可以到information_schema 库的 innodb_trx查询长事务。


select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值