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服务器;作用于所有新建的会话和事务,直至被再次修改
  • 死锁

    • 死锁就是当不同事务均因握住了别的事务需要的"锁",而无法完成事务,所以两个事务都一直在等待对方,并永远没法释放锁。
相关推荐
oradh1 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
z123456789862 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
程序猿DD2 小时前
一个 API Key,统一调用大模型、生图和联网搜索
数据库·网关
TlSfoward3 小时前
抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具
数据库·爬虫·网络协议·搜索引擎·php
数智化管理手记3 小时前
账龄分析手工统计易遗漏?自动账龄分析工具怎么搭建
大数据·网络·数据库·人工智能·数据挖掘
LabVIEW开发4 小时前
NI Package Manager安装LabVIEW时InternalServerError错误
网络·数据库·labview·labview知识·labview功能·labview程序
SelectDB4 小时前
PostgreSQL 实时同步到 Apache Doris:一站式 CDC 解决方案
数据库
欲速不达88204 小时前
Mysql并发DML锁等待的优化
数据库·mysql
Database_Cool_4 小时前
AI Agent 长期记忆怎么存?阿里云 PolarDB-X 对接 Mem0 记忆框架实践
数据库·阿里云
会编程的土豆5 小时前
数据库范式
数据库·oracle