MySQL事务与锁机制详细讲解

事务与锁机制是数据库系统中非常重要的概念,尤其在 MySQL 这样的关系型数据库中,它们决定了数据的 一致性完整性并发控制。下面我将详细讲解事务和锁机制,分步骤深入分析。


一、事务(Transaction)

1. 什么是事务?

事务是一组操作的集合,这些操作要么全部执行成功,要么全部失败回滚,保证数据库的 一致性完整性

2. 事务的四大特性(ACID)

  • A - 原子性(Atomicity)
    事务中的所有操作是一个不可分割的整体,要么全部执行,要么全部不执行。

    例子:银行转账,A账户转100元给B账户,要么两步都完成(A扣款,B加款),要么都不完成(回滚)。

  • C - 一致性(Consistency)
    事务开始前和结束后,数据库保持一致的状态。

    例子:无论事务成功与否,两个账户的总金额保持不变。

  • I - 隔离性(Isolation)
    并发执行的事务互不影响,每个事务的操作在完成前对其他事务是不可见的。

    例子:当两个事务同时更新同一条数据时,事务 A 的操作不会影响事务 B,反之亦然。

  • D - 持久性(Durability)
    一旦事务提交,数据会永久保存,即使系统崩溃也不会丢失。

    例子:事务提交后,数据写入磁盘,保证数据不丢失。


3. MySQL 事务的实现

MySQL 支持事务的存储引擎是 InnoDB。其他存储引擎(如 MyISAM)不支持事务。

事务的基本语法

sql

-- 开始事务 START TRANSACTION; -- SQL 操作 UPDATE account SET balance = balance - 100 WHERE name = 'A'; UPDATE account SET balance = balance + 100 WHERE name = 'B'; -- 提交事务 COMMIT; -- 回滚事务 ROLLBACK;

事务的两种结束方式
  1. 提交(COMMIT):事务中的所有操作成功完成,并永久保存。
  2. 回滚(ROLLBACK):撤销事务中的所有操作,数据库回到事务开始时的状态。
自动提交模式
  • 在 MySQL 中,默认开启 自动提交模式。每执行一条 SQL 语句,MySQL 会自动提交。
  • 关闭自动提交:
    
    

    sql

    复制代码

    SET autocommit = 0;


二、事务的隔离级别

1. 为什么需要隔离级别?

在并发环境下,多个事务同时操作数据库,会引发 并发问题,如脏读、不可重复读和幻读。

2. 并发问题

  • 脏读(Dirty Read)
    一个事务读到了另一个未提交事务修改的数据。
  • 不可重复读(Non-Repeatable Read)
    在同一事务中,前后两次查询的数据不一致,因为其他事务修改了数据。
  • 幻读(Phantom Read)
    在同一事务中,前后两次查询结果的行数不一致,因为其他事务插入/删除了数据。

3. MySQL 的四种隔离级别

MySQL 支持 四种事务隔离级别,从低到高依次是:

隔离级别脏读不可重复读幻读特点
Read Uncommitted允许允许允许最低级别,读到未提交数据
Read Committed禁止允许允许只读取已提交数据(Oracle默认)
Repeatable Read禁止禁止允许可重复读(MySQL 默认级别)
Serializable禁止禁止禁止最高级别,完全串行化操作
设置事务隔离级别

sql

复制代码

-- 查看当前隔离级别 SELECT @@TRANSACTION_ISOLATION; -- 设置隔离级别为 Repeatable Read SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;


三、锁机制

1. 为什么需要锁?

在并发操作中,多个事务可能对同一资源进行读写操作,为了防止数据不一致或损坏,MySQL 采用锁机制来控制并发访问。

2. MySQL 锁的分类

MySQL 的锁主要分为以下几类:

1)按照锁的粒度分类
  • 表锁(Table Lock)

    • 锁定整个数据表。
    • 粒度大,开销小,适用于读多写少的场景。
    • MyISAM 存储引擎使用表锁。
  • 行锁(Row Lock)

    • 锁定某一行记录。
    • 粒度小,开销大,适用于高并发场景。
    • InnoDB 支持行锁。
2)按照锁的类型分类
  • 共享锁(S锁)
    允许多个事务同时读数据,互不影响。

    
    

    sql

    复制代码

    SELECT * FROM table_name LOCK IN SHARE MODE;

  • 排他锁(X锁)
    排他性地锁定数据,其他事务无法读写被锁定的数据。

    
    

    sql

    复制代码

    SELECT * FROM table_name FOR UPDATE;

3)间隙锁(Gap Lock)
  • 间隙锁 用于防止幻读,锁定一个范围内的数据,甚至包括不存在的数据。
  • 发生在 Repeatable Read 隔离级别 下。

3. 锁的实现方式

在 InnoDB 中,锁是通过 索引 实现的。如果查询未使用索引,InnoDB 会退化为表锁。

行锁与索引

sql

复制代码

-- 通过主键索引加行锁 SELECT * FROM table_name WHERE id = 1 FOR UPDATE; -- 未使用索引,退化为表锁 SELECT * FROM table_name WHERE name = '西瓜' FOR UPDATE;


四、事务与锁的结合使用

在实际开发中,事务和锁通常结合使用。例如:


sql

复制代码

START TRANSACTION; -- 通过行锁确保事务的隔离性 SELECT * FROM account WHERE name = 'A' FOR UPDATE; UPDATE account SET balance = balance - 100 WHERE name = 'A'; SELECT * FROM account WHERE name = 'B' FOR UPDATE; UPDATE account SET balance = balance + 100 WHERE name = 'B'; COMMIT;

  • 使用 FOR UPDATE 加排他锁,确保数据安全。
  • 在高并发下避免 死锁锁等待

总结

  1. 事务 通过 ACID 保证数据一致性。
  2. 隔离级别 决定事务之间的并发控制程度。
  3. 锁机制 控制并发访问,InnoDB 支持行锁、表锁和间隙锁。
  4. 结合事务和锁,可以实现高并发下的数据安全操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值