MySQL的事务与锁


1、什么是数据库事务?

答:数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位

事务由事务开始与事务结束之间执行的全部数据库操作组成

2、事务的四大特性是什么?

答:分别是:

  • 原子性:原子性是指包含事务的操作要么全部执行成功,要么全部失败回滚。
  • 一致性:一致性指事务在执行前后状态是一致的
  • 隔离性:一个事务进行的修改在最终提交之前对其他事务是不可见的
  • 持久性:事务一旦提交,其所作的修改将永久地保存到数据库中。

3、数据库的并发一致性问题

答:当多个事务并发执行时,可能会出现以下问题:

  • 脏读:事务A更新了数据,但还没有提交,这时事务B读取到事务A更新后的数据,然后事务A回滚了,事务B读取到的数据就成为脏数据了。
  • 不可重复读:事务A对数据进行多次读取,事务B在事务A多次读取的过程中执行了更新操作并提交了,导致事务A多次读取到的数据并不一致。
  • 幻读:事务A在读取数据后,事务B向事务A读取的数据中插入了几条数据,事务A再次读取数据时发现多了几条数据,和之前读取的数据不一致。
  • 丢失修改:事务A和事务B都对同一个数据进行修改,事务A先修改,事务B随后修改,事务B的修改覆盖了事务A的修改。

不可重复度和幻读看起来比较像,它们主要的区别是:在不可重复读中,发现数据不一致主要是数据被更新了。在幻读中,发现数据不一致主要是数据增多或者减少了。

4、数据库的隔离级别有哪些?

答:数据库的隔离级别有四个,分别是:

  • 未提交读:一个事务在提交前,它的修改对其他事务也是可见的。
  • 提交读:一个事务提交之后,它的修改才能被其他事务看到。
  • 可重复读:在同一个事务中多次读取到的数据是一致的。
  • 串行化:需要加锁实现,会强制事务串行执行。

数据库的隔离级别分别可以解决数据库的脏读、不可重复读、幻读等问题。,如下:

在这里插入图片描述

MySQL的默认隔离级别是可重复读。

5、隔离级别是如何实现的?

答:事务的隔离机制主要是依靠锁机制MVCC(多版本并发控制)实现的,提交读和可重复读可以通过MVCC实现,串行化可以通过锁机制实现。

6、什么是MVCC?

答:MVCC(multiple version concurrent control)是一种控制并发的方法,主要用来提高数据库的并发性能。

在了解MVCC时应该先了解当前读和快照读。

  • 当前读:读取的是数据库的最新版本,并且在读取时要保证其他事务不会修该当前记录,所以会对读取的记录加锁。
  • 快照读:不加锁读取操作即为快照读,使用MVCC来读取快照中的数据,避免加锁带来的性能损耗

可以看到MVCC的作用就是在不加锁的情况下,解决数据库读写冲突问题,并且解决脏读、幻读、不可重复读等问题,但是不能解决丢失修改问题。

7、什么是数据库的锁?

答:当数据库有并发事务的时候,保证数据访问顺序的机制称为锁机制。

8、数据库锁类型有哪些?

答:按照锁的粒度可以将MySQL锁分为三种:表级锁行级锁页面锁

在这里插入图片描述

MyISAM默认采用表级锁,InnoDB默认采用行级锁。

从锁的类别上区别可以分为共享锁排他锁

  • 共享锁:共享锁又称读锁,简写为S锁,一个事务对一个数据对象加了S锁,可以对这个数据对象进
    行读取操作,但不能进行更新操作
    。并且在加锁期间其他事务只能对这个数据对象加S锁,不能加X锁。
  • 排他锁:排他锁又称为写锁,简写为X锁,一个事务对一个数据对象加了X锁,可以对这个对象进行
    读取和更新操作
    ,加锁期间,其他事务不能对该数据对象进行加X锁或S锁

9、什么是数据库的乐观锁和悲观锁,如何实现?

答:

乐观锁

  • 系统假设数据的更新在大多数时候是不会产生冲突的,所以数据库只在更新操作提交的时候数据检测冲突,如果存在冲突,则数据更新失败
  • 乐观锁一般通过版本号和CAS算法实现

悲观锁

  • 假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。通俗讲就是每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁
  • 悲观锁一般通过数据库的锁机制实现,对查询语句添加for updata

10、什么是死锁?如何避免?

答:死锁是指两个或者两个以上进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。

在MySQL中:

  • MyISAM是一次获得所需的全部锁,要么全部满足,要么等待,所以不会出现死锁
  • InnoDB存储引擎中,除了单个SQL组成的事务外,锁都是逐步获得的,所以存在死锁问题

如何避免MySQL发生死锁或锁冲突:

  • 如果不同的程序并发存取多个表,尽量以相同的顺序访问表
  • 在程序以批量方式处理数据的时候,如果已经对数据排序,尽量保证每个线程按照固定的顺序来处理记录
  • 在事务中,如果需要更新记录,应直接申请足够级别的排他锁,而不应该先申请共享锁,更新时在申请排他锁,因为在当前用户申请排他锁时,其他事务可能已经获得了相同记录的共享锁,从而造成锁冲突或者死锁。
  • 尽量使用较低的隔离级别
  • 尽量使用索引访问数据,使加锁更加准确,从而减少锁冲突的机会。
  • 合理选择事务的大小,小事务发生锁冲突的概率更低。
  • 尽量用相等的条件访问数据,可以避免Next-Key锁对并发插入的影响。
  • 不要申请超过实际需要的锁级别,查询时尽量不要显示加锁
  • 对于一些特定的事务,可以使用表锁来提高处理速度或减少死锁的概率
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

abcccccccccccccccode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值