MySQL事务隔离级别

一、事务的基本要素

  1. 原子性(Atomicity):事务开始后的所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,就当所有的操作没发生过一样。这是一个整体,不可分割。
  2. 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏。比如A转账给B,A的钱已经扣了,B不可能没收到钱。
  3. 隔离性(Isolation):同一时间只允许一个事务请求统一数据,不同事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束之前,B无法向这张银行卡转账。
  4. 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,且不能回滚。

二、事务的并发问题

  1. 脏读:事务A读取了事务B更新的数据,但是事务B回滚了,那么事务A则读取到的数据是脏数据。
  2. 不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
  3. 幻读:事务A将数据库中所有的数据从数字改为字母,在修改的过程中,事务B插入了一条数字的数据,导致在事务A修改完后发现有一条没有改过来,如幻觉一样,所以叫幻读。
    PS
    1).不可重复读侧重数据的修改,幻读是侧重数据的新增或删除。
    2).解决不可重复读的问题只需锁住满足条件的行,解决幻读的问题只需锁表。

三、事务隔离级别

在这里插入图片描述
可重复读和幻读
在可重复读中,该sql第一次读取到数据后,就将这些数据加锁(悲观锁),其它事务无法修改这些数据,就可以实现可重复读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。

数据库默认隔离级别: mysql —repeatable-read,oracle,sql server —read commited

为什么MySQL不和Oracle一样,因为在MySQL5.0之前,binlog只支持statement这种格式,而这种格式会导致MySQL在read-committed级别下主从复制会产生逻辑bug。比如在多事务下,有顺序先后的不同的数据更新操作,记录到binlog的顺序会与之相反,从库同步根据binlog日志的记录顺序依次执行,就会产生不一样的结果,导致主从不一致。
解决方案:

  1. 现在版本已经有了多种格式的binlog日志,可以改为row格式,此时基于行的复制,好处是记录详细,每次数据更新都会记录原值,所以不会导致主从复制不一致的问题,但是日志文件常比较大。
  2. 隔离级别设置为repeatable-read,但是该级别会有间隙锁(为解决幻读)。在一个事务范围查找,并请求共享或者排他锁的时候,InnoDB会给符合条件的已有数据记录的索引项加锁,InnoDB对于键值在查询条件范围内但不存在的记录也会加锁,叫做“间隙锁”。在并发时,多个事务同时对一个区间加上了间隙锁,就会导致死锁。

四、对比不可重复读(RC)和可重复读(RR)

项目上一般只有这两种隔离级别,读未提交和串行化一般不用。
why?:

  1. 读未提交会产生脏读,这是不允许的。
  2. 串行化,每次读操作都会加锁快照读失效,一般MySQL使用自带的分布式事务功能时才使用该隔离级别。总的来说,强一致性事务,性能不佳。

1)、RR隔离级别下,由于间隙锁的存在,在并发情况下死锁几率大。
2)、RR隔离级别下,条件列未命中索引会锁表,RC只会锁行。

在RC隔离级别下,其先走聚簇索引,扫描全表,然后MySQL会根据过滤条件,将不满足的用unlock_row方法,把不满足条件的行记录释放锁。而RR是走聚簇索引,进行全部扫描,最后会将整个表锁上。

3)、RC隔离级别下,半一致性读(semi-consistent)特性增加了update操作的并发性。

在5.1.15的时候,innodb引入了一个概念叫做“semi-consistent”,减少了更新同一行记录时的冲突,减少锁等待。

所谓半一致性读就是,一个update语句,如果读到一行已经加锁的记录,此时InnoDB返回记录最近提交的版本,由MySQL上层判断此版本是否满足update的where条件。若满足(需要更新),则MySQL会重新发起一次读操作,此时会读取行的最新版本(并加锁)!

总结: 所以,虽然MySQL默认隔离级别为RR,然而由于现如今高并发的现实问题,大部分互联网项目,MySQL采用RC的为主。

五、两个疑问

Q1: 在RC级别下,不可重复读问题需要解决么?

A1: 不用解决,这个问题是可以接受的!毕竟你数据都已经提交了,读出来本身就没有太大问题!Oracle的默认隔离级别就是RC,你们改过Oracle的默认隔离级别么?

Q2: 在RC级别下,主从复制用什么binlog格式?

A2: OK,在该隔离级别下,用的binlog为row格式,是基于行的复制!Innodb的创始人也是建议binlog使用该格式!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值