SQL - 事务

  • 事务是代表单个工作单元的一组SQL语句,当我们需要对数据库进行多次更改的情况下,要使用事务,我们希望所有这些更改作为一个单元一起成功或失败

  • 事务属性 (ACID)

    • 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成;
    • 一致性(Consistency):事务完成后,数据库必须从一个一致状态转化到另一个一致状态,数据库始保持一致的状态;
    • 隔离性(Islation):一个事务的执行不应影响其他事务的执行;
    • 持久性(Durability):一旦事务提交,其结果应该永久保存在数据库中,即使系统发生故障;
  • 创建事务

    • 流程:

      • start transaction; //创建一个事务
      • 添加更改操作语句;
      • commit or rollback;
    • 两种提交方式:

      • commit 关闭此事务,提交事务的所有更改
      • rollback 退回事务并撤销所有更改,该事务视为未被创建
  • 并发与锁定

    • 当一个用户修改其他用户正在检索或修改的数据时,会产生并发问题。
    • 如果一个事务试图修改一行或多行时,它会给这些行上锁,这个锁防止其他事务修改这些行,直到第一个事务完成,被提交或被退回。
    • 但 在某些特殊情况下,默认行为不足以满足应用里的特定场景,可以改写默认行为。默认的锁粒度是行级锁。
  • 常见的并发问题和解决方法

    • 1.丢失更新

      • 当两个事务尝试更新相同的数据并且没有上锁时,就会发生这种情况,比如两个事务更新同一条记录的不同列的信息,较晚提交的事务会覆盖较早事务做的更改,使得较早事务做的更改缺失。
      • 使用锁,防止两个事务同时更新同样的数据,MySQL提供的默认锁的锁粒度是行级锁。
    • 2.脏读

      • 一个事务读取了尚未被提交的数据,如果该数据被退回的话,该事务就是读取了一个不存在的数据,就是脏读。
      • 为了解决这个问题,我们需要为事务建立隔离级别,"读已提交",这样事务修改的数据不会立马被其他事务读取,除非它提交了。
    • 3.不可重复读(不一致读)

      • 当我们在事务中添加更多隔离时,我们可以保证事务只能读取已提交的数据,但如果在事务过程中,读取了某个数据两次,并得到了不同的结果就是不可重复读问题。
      • 我们就需要增加事务隔离级别,我们要将它与其他事务隔离,"可重复读",确保数据更改对该事务不可见,只看事务开始前那一刻的数据信息。
    • 4.幻读

      • 对于突然出现或者缺失的数据,我们无法在查询中看到它们,因为它们是在执行查询后才添加、更新、删除的。
      • 为此,我们有另一个隔离级别为"序列化",它能保证当有别的事务在更新数据时,我们的事务能够知晓变动,如果有其他事务修改了可能影响查询结果的数据,我们的事务必须等它们完成,这样事务就会按序列化执行。
  • 事务隔离级别

    • 标准的SQL定义了4个事务隔离级别,隔离级别逐渐增高,性能和可扩展性逐渐降低,因为限制了并发。在MySQL中,默认的事务隔离级别是'可重复读'。
    • 读未提交:允许读取未提交的数据,最低的隔离级别
    • 读已提交:给予了我们的事务一定的隔离,使得该事务只能读取已提交的数据,避免了脏读。
    • 可重复读:我们读取的数据是可重复和一致的,就算有其他事务更改了数据,我们会看到首次读取就创建的快照。
    • 序列化:它能保证当有别的事务在更新数据时,我们的事务能够知晓变动,如果有其他事务修改了可能影响查询结果的数据,我们的事务必须等它们完成,这样事务就会按序列化执行。
  • 设置事务隔离级别

    • set transaction isolation level 新隔离级别名称
      • //作用范围:当前事务;只为下一个事务设置隔离级别,read uncommitted,read committed,repeatable read,serializable
    • set session transaction isolation level 新隔离级别名称
      • //作用范围:当前会话;设置当前会话中所有后续事务的隔离级别,直至会话结束或者隔离级别再次更改
    • set global transaction isolation level 新隔离级别名称
      • //作用范围:整个MySQL服务器;作用于所有新建的会话和事务,直至被再次修改
  • 死锁

    • 死锁就是当不同事务均因握住了别的事务需要的"锁",而无法完成事务,所以两个事务都一直在等待对方,并永远没法释放锁。
相关推荐
Hello.Reader25 分钟前
StarRocks实时分析数据库的基础与应用
大数据·数据库
执键行天涯27 分钟前
【经验帖】JAVA中同方法,两次调用Mybatis,一次更新,一次查询,同一事务,第一次修改对第二次的可见性如何
java·数据库·mybatis
yanglamei196237 分钟前
基于GIKT深度知识追踪模型的习题推荐系统源代码+数据库+使用说明,后端采用flask,前端采用vue
前端·数据库·flask
Darling_0039 分钟前
LeetCode_sql_day28(1767.寻找没有被执行的任务对)
sql·算法·leetcode
zxrhhm44 分钟前
SQLServer TOP(Transact-SQL)
sql·sqlserver
工作中的程序员1 小时前
ES 索引或索引模板
大数据·数据库·elasticsearch
严格格1 小时前
三范式,面试重点
数据库·面试·职场和发展
微刻时光1 小时前
Redis集群知识及实战
数据库·redis·笔记·学习·程序人生·缓存
单字叶1 小时前
MySQL数据库
数据库·mysql
mqiqe2 小时前
PostgreSQL 基础操作
数据库·postgresql·oracle