MySQL锁

事务是什么?

  • 事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性
事务有哪些特性?
  • 原子性(Atomicity):事务是一个不可分割的单位,事务中的所有SQL等操作要么都发生,要么都不发生

  • 一致性(Consistency):事务发生前和发生后,数据的完整性必须保持一致

  • 隔离性(Isolation):当并发访问数据库时,一个正在执行的事务在执行完毕前,对应其他的会话是不可见的,多个并发事务之间的数据是相互隔离的。备份的参数 – single-transaction

  • 持久性(Durability):一个事务一旦被提交,它对数据库中的数据改变就是永久性的。如果出了错误,事务也不允许撤销,只能通过“补偿性事务”

MySQL中InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?为什么是这样子的?
  • InnoDB是基于索引来完成行锁。例如在select * from tab_with_index where id = 1 for update中,for update 可以根据条件来完成行锁锁定,并且 id 是有索引键的列,如果 id 不是索引键那么InnoDB将完成表锁,并发将无从谈起
并发事务带来哪些问题?
  • 脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的
  • 丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失
  • 不可重复读(Unrepeatable read): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读
  • 幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读

不可重复读和幻读区别:

  • 不可重复读的重点是修改,幻读的重点在于新增或者删除

    (例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读

    例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读)

简介一下MySQL的MVCC机制 ?
  • MVCC是一种多版本并发控制机制,是MySQL的InnoDB存储引擎实现隔离级别的一种具体方式,用于实现提交读和可重复读这两种隔离级别。MVCC是通过保存数据在某个时间点的快照来实现该机制,其在每行记录后面保存两个隐藏的列,分别保存这个行的创建版本号和删除版本号,然后Innodb的MVCC使用到的快照存储在Undo日志中,该日志通过回滚指针把一个数据行所有快照连接起来
  • 五分钟搞清楚 MVCC 机制
  • redo-log,uodo-log,MVCC

什么是基本表?什么是视图?

  • 基本表是本身独立存在的表,在 SQL 中一个关系就对应一个表。 视图是从一个或几个基本表导出的表。视图本身不独立存储在数据库中,是一个虚表
试述视图的优点?
  • 视图能够简化用户的操作
  • 视图使用户能以多种角度看待同一数据;
  • 视图为数据库提供了一定程度的逻辑独立性;
  • 视图能够对机密数据提供安全保护

什么是乐观锁和悲观锁?

  • 悲观锁:对于同一个数据的并发操作,认为在使用数据时一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。

  • 乐观锁:认为在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)

  • 乐观锁与悲观锁是一种广义上的思想概念,广泛应用于 JDK、数据库乃至工程设计思想中。

  • 悲观锁机制在传统的关系型数据库中使用较广,比如行锁,表锁等,都是在做操作之前先上锁。Java 中 synchronized 和 ReentrantLock 等独占锁也是悲观锁思想的实现。

  • 乐观锁可以用版本号机制或 CAS 算法实现,Java 中的 AtomicInteger 等原子变量类使用的就是乐观锁 CAS 算法。

两种锁的使用场景:
  • 响应速度:如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁
  • 冲突频率:如果冲突频率非常高,建议采用悲观锁,保证成功率,如果冲突频率大,乐观锁会需要多次重试才能成功,代价比较大
  • 重试代价:如果重试代价大,建议采用悲观锁
  • 业务场景:读多写少倾向于乐观锁,读少写多倾向于悲观锁
    在这里插入图片描述

详述一下数据库事务隔离的四个级别 ?

  • Read Uncommitted(读未提交):事务可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。而且可能出现脏读(Dirty Read),即一个事务读取到另一个事务还有没提交的记录

  • Read Committed(读提交) :事务只能看见已经提交的事务所做的改变。这种隔离级别可能导致不可重复读(Nonrepeatable Read),即同一事务的其他实例在该实例处理其间可能会有新的 commit,所以同一个查询操作执行两次或多次的结果不一致

  • Repeatable Read(可重复读) : 事务的多个实例在并发读取数据时读到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(PhantomRead),它是指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的 “幻影” 数据

  • Serializable(串行化) :通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争

  • MySQL 的默认事务处理级别是可重复读,Oracle 的默认事务处理级别是读提交

如何实现一个分布式锁?

通常有三种方案:

  • 基于数据库实现。 利用主键唯一的特性,如果有多个请求同时提交到数据库的话,数据库会保证只有一个操作可以成功,那么我们就可以认为操作成功的那个线程获得了该方法的锁,当方法执行完毕之后,想要释放锁的话,删除这条数据库记录即可。易于理解,但是可能出现单点故障,性能也可能成为瓶颈

  • 基于 redis 实现。 使用 redis 的 setnx ()、get () 和 getset () 方法来实现分布式锁。

    • setnx (lockkey, 当前时间 + 过期超时时间),如果返回 1,则获取锁成功;如果返回 0 则没有获取到锁,转向 B

    • get (lockkey) 获取值 oldExpireTime ,并将这个 value 值与当前的系统时间进行比较,如果小于当前系统时间,则认为这个锁已经超时,可以允许别的请求重新获取,转向 C

    • 计算 newExpireTime = 当前时间 + 过期超时时间,然后 getset (lockkey, newExpireTime) 会返回调用前的 lockkey 的值 currentExpireTime

    • 判断 currentExpireTime 与 oldExpireTime 是否相等,如果相等,说明当前 getset 设置成功,获取到了锁。如果不相等,说明这个锁又被别的请求获取走了,那么当前请求可以直接返回失败,或者继续重试

    • 在获取到锁之后,当前线程可以开始自己的业务处理,当处理完毕后,比较自己的处理时间和对于锁设置的超时时间,如果小于锁设置的超时时间,则直接执行 delete 释放锁;如果大于锁设置的超时时间,则不需要再锁进行处理

  • 基于 Zookeeper 实现分布式锁。 利用临时节点与 watch 机制。每个锁占用一个普通节点 /lock,当需要获取锁时在 /lock 目录下创建一个临时节点,创建成功则表示获取锁成功,失败则 watch/lock 节点,有删除操作后再去争锁。临时节点好处在于当进程挂掉后能自动上锁的节点自动删除即取消锁


文章推荐:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值