MySQL进阶之事务
目录
什么是事务
事务(Transaction)是数据库管理系统(DBMS)中的一个概念,用于将一系列操作作为一个逻辑单元进行处理。事务可以保证数据库在执行期间的一致性和完整性。也就是要么一起完成,要么一起失败,
事务的四大特性(ACID)
原子性(Atomicity):事务被视为不可分割的原子操作,要么全部执行成功,要么全部回滚。如果在事务执行过程中发生错误,所有对数据库的修改都会被撤销,使得数据库状态回滚到事务开始之前的状态。
一致性(Consistency):事务的执行不能违反数据库的完整性约束。在事务开始和结束时,数据库必须保持一致的状态,即遵循定义的规则和约束条件。
隔离性(Isolation):每个事务的操作都应该与其他并发事务相互隔离,以避免数据的冲突和干扰。即使多个事务并发执行,也不能破坏数据的一致性。
持久性(Durability):一旦事务提交,其对数据库所做的修改应该永久保存,即使在系统故障或崩溃后仍然有效。
基础用法
- START TRANSACTION:开始事务
start transaction;
- ROLLBACK:回滚
rollback;
- COMMIT:提交事务
commit;
事务并发是常遇到的问题
- 脏读(Dirty Read):脏读指的是一个事务读取了另一个事务尚未提交的数据,当被读取的数据被回滚时,读取到的内容就是无效的。这种情况下,读取到的数据可能是临时的或错误的,因为尚未提交的事务可能会回滚导致数据的改变。
- 不可重复读(Non-repeatable Read):不可重复读指的是在同一个事务内,对于相同的查询,多次读取可能会得到不同的结果。这是因为在读取期间,其他事务对所读取的数据进行了修改或删除,导致结果的不一致。
- 幻读(Phantom Read):幻读指的是在同一个事务内,对于相同的查询,多次读取可能会发现新增或删除的数据。这是因为在读取期间,其他事务对表中的数据进行了插入、更新或删除操作,导致结果的不一致。
事务的隔离级别
1.读未提交( read uncommitted):最低的隔离级别。允许一个事务读取到另一个事务尚未提交的数据,可能导致脏读、不可重复读和幻读问题。
2.读已提交(read committed):要求一个事务只能读取到其他已经提交的事务的数据。避免了脏读问题,但仍可能出现不可重复读和幻读问题。
3.可重复读(repeatable read):要求一个事务在执行期间多次读取同一数据时,结果保持一致。该隔离级别通过锁定被读取的数据来避免不可重复读问题,但仍可能出现幻读问题。
4.串行化(serializable):最高的隔离级别,要求事务串行执行,彼此之间没有任何并发操作。完全避免了脏读、不可重复读和幻读问题,但会降低并发性能。
设置隔离级别示例:
#设置当前mysql连接的隔离级别:
set session transaction isolation level read uncommitted;
#设置数据库系统的全局的隔离级别:
set global transaction isolation level read uncommitted;
然后打开两个独立的MySQL数据库模拟并发环境
接下来开始正式模拟
读未提交(read uncommitted)
首先将两个程序的隔离等级都设置为read uncommitted
set session transaction isolation level read uncommitted;
在程序1中开启事务并执行语句,但不提交事务
此时在程序2中执行查询操作,读未提交的数据就可能导致脏读、不可重复读和幻读问题,上述示例中程序2会读到未提交的数据,这就是脏读
读已提交(read committed)
设置隔离等级为read committed
set session transaction isolation level read committed;
在程序1中开启事务并执行语句并提交事务,可以看到程序2查询结果并不受事务影响,只有当提交事务后才会查询到不同结果
可重复读(repeatable read)
repeatable read是MySQL中默认的隔离机制,该机制下,当一个事务读取数据时,其他并发的事务不允许修改这些数据,这意味着在一个事务中读取的数据在该事务结束之前将保持不变。
set session transaction isolation level repeatable read;
然而,在可重复读隔离级别下,其他事务可以插入新的数据行,因此可能会出现幻读(Phantom Read)现象。
串行化(serializable)
set session transaction isolation level serializable;
串行化隔离级别提供了最高的一致性和数据完整性,但并发性较差,其实现原理也和可重复读基本一致,因此不再做代码演示
回滚(rollback)
基本语法:
start transaction; -- 开启事务
savepoint 节点名称; -- 设置存档点
rollback 节点名称; -- 回到存档节点之前的数据
commit; -- 提交事务
示例:
-- 禁用自动提交事务
set autocommit = 0;
-- 开启事务
start transaction;
-- 为emp5添加数据
insert into emp5 (...) values(...);
-- 设置保存点名为AA
savepoint AA;
-- 删除id为9的记录
delete from emp5 where id = 9;
-- 回滚到AA保存点处
rollback to AA; -- 此时的数据是添加数据但是id9的数据并未被删除的时候