MySQL(二)、事务
目录
MySQL系列:
简介
事务是"一组原子性的SQL命令",或者说一个独立的工作单元。如果数据库引擎能够成功地对数据库应用该组SQL的全部语句,那么就执行该组SQL。如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行。也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。
MySQL事务和锁:https://dev.mysql.com/doc/refman/8.0/en/sql-transactional-statements.html
特性
事务具有以下4个特征,ACID:
原子性(Atomicity):事务被视为一个不可分割的最小工作单元,事务中的所有操作要么全部提交成功,要么全部失败回滚;
一致性(Consistency):数据库总是从一个一致性的状态转换到另外一个一致性的状态;
隔离性(Isolation):一个事务所做的修改在最终提交以前,对其他事务是不可见的;
持久性(Durability):一旦事务提交,则其所做的修改就会永久保存到数据库中;
语法
自动提交事务:
默认情况下,MySQL开启了 autocommit 自动提交事务,若没有显式的开启事务则每个SQL都会被认为是一个事务自动执行提交操作。
show variables like "autocommit";
set autocommit=0; -- 或者OFF、False, 表示关闭自动提交
set autocommit=1; -- 或者ON、True, 表示开启自动提交
显式的管理事务:
如果想要显式的在事务中管理SQL,则可以使用下面的命令进行控制。
-- 开启一个事务
BEGIN 或 START TRANSACTION
-- 提交事务,提交此事务中的所有动作;
COMMIT 或 COMMIT WORK
-- 回滚事务,撤销此事务内所有动作;
ROLLBACK 或 ROLLBACK WORK
-- 在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
SAVEPOINT identifier
-- 删除事务的一个保存点;
RELEASE SAVEPOINT identifier
-- 在事务中回滚到指定的保存点;
ROLLBACK TO identifier
-- 设置事务的隔离级别,InnoDB存储引擎提供事务的隔离级别有:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE
SET TRANSACTION
脏读、幻读、不可重复读
在多个事务并发操作时,数据库中会出现下面三种问题:脏读,幻读,不可重复读。
脏读(Dirty Read)
事务A读到了事务B还未提交的数据:
事务A读取的数据,事务B对该数据进行修改还未提交数据之前,事务A再次读取数据会读到事务B已经修改后的数据,如果此时事务B进行回滚或再次修改该数据然后提交,事务A读到的数据就是脏数据,这个情况被称为脏读(Dirty Read)。
幻读(Phantom Read)
事务A进行范围查询时,事务B中新增了满足该范围条件的记录,当事务A再次按该条件进行范围查询,会查到在事务B中提交的新的满足条件的记录(幻行 Phantom Row)。
不可重复读(Unrepeatable Read)
事务A在读取某些数据后,再次读取该数据,发现读出的该数据已经在事务B中发生了变更或删除。
幻读和不可重复度的区别:
- 幻读:在同一事务中,相同条件下,两次查询出来的 记录数 不一样;
- 不可重复读:在同一事务中,相同条件下,两次查询出来的 数据 不一样;
隔离级别
为了解决数据库中事务并发所产生的问题,在标准SQL规范中,定义了四种事务隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
MySQL事务隔离级别:https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
通过修改MySQL系统参数来控制事务的隔离级别,在MySQL8中该参数为 transaction_isolation ,在MySQL5中该参数为 tx_isolation :
MySQL8:
-- 查看系统隔离级别:
SELECT @@global.transaction_isolation;
-- 查看当前会话隔离级别
SELECT @@transaction_isolation;
-- 设置当前会话事务隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 设置全局事务隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
事务的四个隔离级别:
- 未提交读(READ UNCOMMITTED):所有事务都可以看到其他事务未提交的修改。一般很少使用;
- 提交读(READ COMMITTED):Oracle默认隔离级别,事务之间只能看到彼此已提交的变更修改;
- 可重复读(REPEATABLE READ):MySQL默认隔离级别,同一事务中的多次查询会看到相同的数据行;可以解决不可重复读,但可能出现幻读;
- 可串行化(SERIALIZABLE):最高的隔离级别,事务串行的执行,前一个事务执行完,后面的事务会执行。读取每条数据都会加锁,会导致大量的超时和锁争用问题;
问:如何保证 REPEATABLE READ 级别绝对不产生幻读?
答:在SQL中加入 for update (排他锁) 或 lock in share mode (共享锁)语句实现。就是锁住了可能造成幻读的数据,阻止数据的写入操作。MySQL的 锁 相关的内容会在后面的篇章内详细介绍。
希望本文对你有帮助,请点个赞鼓励一下作者吧~ 谢谢!
下一篇: Python中字典的基本操作