• 事务和锁


    文章来自

    基础事务使用

    # 事务
    begin;  # 开始事务
    insert into runoob_transaction_test value(5);
    insert into runoob_transaction_test value(6);
    commit; # 提交事务
    

    四个隔离级别
    设置后在使用事务时会产生特殊的效果

    • read uncommitted(未提交读),隔离级别最低
    set session transaction isolation level read uncommitted;
    
    A:启动事务,此时数据为初始状态
    B:启动事务,更新数据,但不提交
    A:再次读取数据,发现数据已经被修改了,这就是所谓的“脏读”
    B:回滚事务
    A:再次读数据,发现数据变回初始状态
    
    • read committed(已提交读,默认)
    set session transaction isolation level read committed;
    
    A:启动事务,此时数据为初始状态
    B:启动事务,更新数据,但不提交
    A:再次读数据,发现数据未被修改
    B:提交事务
    A:再次读取数据,发现数据已发生变化,说明B提交的修改被事务中的A读到了,这就是所谓的“不可重复读”
    
    • repeatable read(可重复读),这里涉及的知识点有事务版本,数据链
    A:启动事务,此时数据为初始状态
    B:启动事务,更新数据,但不提交
    A:再次读取数据,发现数据未被修改
    B:提交事务
    A:再次读取数据,发现数据依然未发生变化,这说明这次可以重复读了
    B:插入一条新的数据,并提交
    A:再次读取数据,发现数据依然未发生变化,虽然可以重复读了,但是却发现读的不是最新数据,这就是所谓的“幻读”
    A:提交本次事务,再次读取数据,发现读取正常了
    
    • 将A的隔离级别设置为可串行化(Serializable)
    A:启动事务,此时数据为初始状态
    B:发现B此时进入了等待状态,原因是因为A的事务尚未提交,只能等待(此时,B可能会发生等待超时)
    A:提交事务
    B:发现插入成功
    
    # serializable完全锁定字段,若一个事务来查询同一份数据就必须等待,直到前一个事务完成并解除锁定为止。是完整的隔离级别,会锁定对应的数据表格,因而会有效率的问题
    

    死锁

    • A更新lives表,请求lives的排他锁,成功。
    • B更新earth表,请求earth的排他锁,成功。
    • 5秒过后
    • A更新earth,请求earth的排它锁,由于B占用着earth的排它锁,等待。
    • B更新lives,请求lives的排它锁,由于A占用着lives的排它锁,等待。

    这样相互等待对方释放资源,造成资源读写拥挤堵塞的情况,就被称为死锁现象,也叫做阻塞。而为什么会产生,上例就列举出来啦。

    然而数据库并没有出现无限等待的情况,是因为数据库搜索引擎会定期检测这种状况,一旦发现有情况,立马选择一个事务作为牺牲品。牺牲的事务,将会回滚数据。有点像两个人在过独木桥,两个无脑的人都走在啦独木桥中间,如果不落水,必定要有一个人给退回来。这种相互等待的过程,是一种耗时耗资源的现象,所以能避则避。

    哪个人会被退回来,作为牺牲品,这个我们是可以控制的。控制语法:

    set deadlock_priority  <级别>
    死锁处理的优先级别为 low<normal<high,不指定的情况下默认为normal,牺牲品为随机。如果指定,牺牲品为级别低的。
    
    还可以使用数字来处理标识级别:-10到-5为low,-5为normal,-5到10为high。
    

    减少死锁,高并发带来的死锁是不可避免的,所以我们只能让其变的更少。

    • 按照同一顺序访问数据库资源,上述例子就不会发生死锁啦
    • 保持是事务的简短,尽量不要让一个事务处理过于复杂的读写操作。事务过于复杂,占用资源会增多,处理时间增长,容易与其它事务冲突,提升死锁概率。
    • 尽量不要在事务中要求用户响应,比如修改新增数据之后在完成整个事务的提交,这样延长事务占用资源的时间,也会提升死锁概率。
    • 尽量减少数据库的并发量。
    • 尽可能使用分区表,分区视图,把数据放置在不同的磁盘和文件组中,分散访问保存在不同分区的数据,减少因为表中放置锁而造成的其它事务长时间等待。
    • 避免占用时间很长并且关系表复杂的数据操作。
    • 使用较低的隔离级别,使用较低的隔离级别比使用较高的隔离级别持有共享锁的时间更短。这样就减少了锁争用。

    建议把mysql的锁级别设置在默认就好,使用代码去实现乐观锁,避免mysql的死锁

  • 相关阅读:
    关于前端框架讨论的链接
    和BEM的战斗:10个常见问题及如何避免
    BEM —— 源自Yandex的CSS 命名方法论
    JavaScript 语句后应该加分号么?
    彻底搞懂word-break、word-wrap、white-space
    ios UIImageWriteToSavedPhotosAlbum报错 NSPhotoLibraryAddUsageDescription
    Emmet使用手册
    vue-cli入门之项目结构分析
    ios移动端原生滚动条滚动不灵敏问题
    ios点击事件失效
  • 原文地址:https://www.cnblogs.com/pengdt/p/13062299.html
Copyright © 2020-2023  润新知