MySQL事务

本文介绍了MySQL事务的基本概念,包括其四大特性(原子性、一致性、隔离性和持久性),以及如何手动操作事务。讨论了事务的不同隔离级别,如读未提交、读已提交、可重复读和串行化,以及它们可能导致的问题,如脏读、不可重复读和幻读。此外,还提到了行锁、表锁、间隙锁在解决并发问题中的作用,以及MVCC多版本并发控制机制。最后,文章阐述了隐式事务和显式事务的区别,并说明了如何设置和查看事务的隔离级别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事务定义

事务是由多条SQL语句构成,用于完成对数据库的多次修改。这些SQL所做的是一件事,它们是一个整体。所以要么全部执行成功,要么全部执行失败。为了保证这个,事务必须要有两个命令commit(提交用于全部成功),rollback(回滚用于全部失败)

事务四大特征(ACID)

原子性Atomicity:事务当中的多条SQL要么全部成功,要么全部失败。
一致性Consistency:事务执行后,如果成功要符合预期,比如转账,转账人账户金额要减少预期的金额,收款人账户要增加预期的金额;如果失败,数据要回到没有执行事务之前的状态,比如转账,转账人和收款人的账户金额都要跟执行转账事务之前的一样。
隔离性Isolation:一个事务执行过程中操作数据,不受并发的其他事务的影响。即保证数据在此事务中操作时不被其他事务操作。隔离性类似于Java的多线程安全问题。
持久性Durability:事务执行完,数据要更新到数据库,即数据的持久化。

事物的手动操作

开启事务:START TRANSACTION | BEGIN
提交事务:COMMIT
事务回滚:ROLLBACK

事务的隔离级别

隔离级别有哪些

	READ UNCOMMITTED:读未提交,读到别的事务未提交的数据。此数据如果最终未提交,则本次读取就是脏读。
	READ COMMITTED:读已提交,读到别的线程提交过的数据。
	REPETABLE READ:可重复读,在事务中,多次执行同一个查询,得到的结果一样。会产生幻读
	SERAILIZABLE:串行,多个事务排队执行,一个事务执行完,另一个事务再执行。效率较低,用的比较少。
	InnoDB 存储引擎在分布式事务的情况下一般会用到 SERIALIZABLE 隔离级别。

《MySQL 技术内幕:InnoDB 存储引擎(第 2 版)》7.7 章这样写到:InnoDB 存储引擎提供了对 XA 事务的支持,并通过 XA 事务来支持分布式事务的实现。分布式事务指的是允许多个独立的事务资源(transactional resources)参与到一个全局的事务中。事务资源通常是关系型数据库系统,但也可以是其他类型的资源。全局事务要求在其中的所有参与的事务要么都提交,要么都回滚,这对于事务原有的 ACID 要求又有了提高。另外,在使用分布式事务时,InnoDB 存储引擎的事务隔离级别必须设置为 SERIALIZABLE。

隔离级别的设置

	方式一:SQL命令设置
	SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
    方式二:MySQL配置文件设置

可以在my.ini文件中使用transaction-isolation选项来设置服务器的缺省事务隔离级别:
– READ-UNCOMMITTED
– READ-COMMITTED
– REPEATABLE-READ
– SERIALIZABLE
• 例如:
[mysqld]
transaction-isolation = READ-COMMITTED

事务隔离级别的查看:

show variables like ‘tx_isolation’ 或者select @@tx_isolation
show variables like ‘transaction_isolation’ 或者select @@transaction_isolation

脏读

读未提交隔离级别下产生,读到别的事务未提交的数据。此数据如果最终未提交,则本次读取就是脏读。

不可重复读

读已提交隔离级别下产生,在一次事务中,同一条数据第二次读到结果和第一次读到结果不一样。因为在此期间别的事务修改并提交这条数据。

幻读

可重复读隔离级别下产生,一个事务中只有刚刚进入事务时,才会从数据库读取一次数据,之后只要不出事务,所有的读操作都是直接获取第一次的结果,这是为了保证可重复读,确保一个事务中每次读操作读到的结果都一样。这个事务进行的同时另外一个事务添加了或删除了一条满足第一个事务查询条件的数据。第一个事务读不出来有这种变化,但是当要插入与第二个事务刚刚插入的那条数据主键相同的数据时就会提示主键重复,或者要删除与第二个事务刚刚删除的那条数据主键相同的数据时就会提示数据不存在。

幻读和不可重复读的区别:

幻读指在事务中读不出数据库中数据条数的变化,不可重复读指同一条数据,在事务中不同时间读出的结果不一样

幻读的处理

行锁基础上使用间隙锁,行锁只能锁住数据不被修改,不能阻止其他事务插入或删除其他数据行
在重复读隔离级别下使用 select …for update会自动启动间隙锁
启动间隙锁既可以阻止数据行不被修改,也可阻止数据行的插入和删除

当前读和快照读:

这两个概念是针对可重复读隔离级别说的
当前读 select …for update,读取数据库中实时数据
快照读 select … 普通的select,在事务中的快照读只会获取刚进入事务时第一次读到的结果

行锁,表锁,间隙锁

行锁:select… for update 查询条件为唯一主键,如果查询条件是非主键会锁柱整张表
间隙锁:数据行之间的间隙也被锁住,如id=5的数据和id=7之间的间隙如果加上间隙锁,则7>id>5之间的数据就无法插入和删除,就解决了幻读 例如:select * from table where id>5 and id <7 for update
间隙锁是在可重复读隔离级别下才会生效的

MVCC 机制 (多版本并发控制)

参考 https://blog.youkuaiyun.com/qq_42799615/article/details/110942949

隐式事务和显式事务

MySQL默认情况下开启自动提交,每一条DML(insert,update,delete)都会开启一个事务,并自动提交。这就是隐式事务。
若要手动控制事务,即显式事务两种方式:
1、set autocommit=0;
//执行事务相关SQL
commit | rollback;
2、START TRANSACTION | BEGIN
//执行事务相关SQL
commit | rollback;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值