zoukankan      html  css  js  c++  java
  • 事务的四大特性

      

    事务的四大特性是事务本身具有的特点。简称ACID。

    原子性(Atomicity)
    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

    一致性(Consistency)
    事务前后数据的完整性必须保持一致。

    持久性(Durability)
    持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

    隔离性(Isolation)
    事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

    由于事务的前三大特性数据库可以帮我们保证。需要讨论隔离性;

    隔离性(Isolation)

      我们知道数据库的隔离性问题本质上就是多线程并发安全性问题。

      可以用锁来解决多线成并发安全问题,但是如果用了锁,必然会造成程序的性能大大的下降.对于数据库这种高并发要求的程序来说这是不可接受的.

      我们可以具体分析下隔离性产生的细节:

        如果两个线程并发修改,必然产生多线程并发安全问题,必须隔离开

        如果两个线程并发查询,必然没有问题,不需要隔离

        如果一个线程修改,一个线程查询,在不同的应用场景下有可能有问题,有可能没问题。

    隔离性可能造成的问题:

      1.脏读:
        一个事务读取到另一个事务未提交的数据

      2.不可重复读:
        一个事务多次读取数据库中的同一条记录,多次查询的结果不同(一个事务读取到另一个事务已经提交的数据)

      3.虚读(幻读)
        有可能出现,有可能不出现:
          一个事务多次查询整表数据,多次查询时,由于有其他事务增删数据, 造成的查询结果不同(一个事务读取到另一个事务已经提交的数据)

    数据库的隔离级别:

      1.查询数据库的隔离级别:select @@tx_isolation;

      2.修改数据库的隔离级别:  

        set [session/global] transaction isolation level xxxxxx;
        set global transaction isolation level serializable;
        不写默认就是session,修改的是当前客户端和服务器交互时是使用的隔离级别,并不会影响其他客户端的隔离级别
        如果写成global,修改的是数据库默认的隔离级别(即新开客户端时,默认的隔离级别),并不会修改当前客户端和已经开启的客户端的隔离级别

    数据库中的锁:

      

      1. 共享锁
        共享锁和共享锁可以共存,共享锁和排他锁不能共存.在非Serializable隔离级别下做查询不加任何锁,在Serializable隔离级别下做查询加共享锁.
        案例演示:打开两个mysql客户端,将隔离级别都设置为Serializable级别,
        set session transaction isolation level Serializable;--设置后查询加了共享锁
        分别在两个客户端中查询:
        start transaction;
        select * from account;--都能查询出数据,说明共享锁可以共存。
      2. 排他锁
        排他锁和共享锁不能共存,排他锁和排他锁也不能共存,在任何隔离级别下做增删改都加排他锁.

      3.可能的死锁

        mysql可以自动检测到死锁,错误退出一方执行另一方

    更新丢失问题:

      1. 更新丢失问题的产生
        两个并发的事务基于同一个查询结果进行修改,后提交的事务忽略了先提交的事务对数据库的影响,造成了先提交的事务对数据库的影响丢失,这个过程就叫做更新丢失

      2.更新丢失解决方案:

        将数据库设置为Serializable隔离级别,但是我们一般不会将数据库设置为Serializable。那么在非Serializable下又如何解决更新丢失?可以使用乐观锁、悲观锁。

        乐观锁和悲观锁并不是数据库中真实存在的锁,而是两种解决方案的名字。
          (1)悲观锁:
              在查询时,手动的加排他锁,从而在查询时就排除可能的更新丢失。
            select * from users for update;
          (2)乐观锁:
            在表中设计添加一个版本字段,在进行修改时,要求根据具体版本进行修改,
            并将版本字段+1,如果更新失败,说明更新丢失,需要重新进行更新。
            两种解决方案各有优缺点,如果查询多修改少,用乐观锁.
            如果修改多于查询,用悲观锁。

  • 相关阅读:
    flutter 反序列化
    系统架构师-系统开发基础
    java Lambda表达式
    java异常
    HTTP缓存了解(一)
    设计模式(一):策略模式
    配置自己的ubuntu
    正则表达式:贪婪与非贪婪
    .htaccess文件
    mysql协议简析
  • 原文地址:https://www.cnblogs.com/tongxuping/p/7003213.html
Copyright © 2011-2022 走看看