mysql 事务浅析

事务是什么

事务是指,作为单个逻辑工作单元执行的一系列操作。
这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。

事务的4大特性

事务具有4个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

  • 原子性:事务作为一个整体执行,必须是原子工作单元,对数据进行修改时,要么全部执行,要么全部不执行。

  • 一致性:在事务开始之前和完成之后,数据库确保是从一个一致性状态到另一个一致性,一致性状态的含义是数据库中的数据应满足完整性约束

  • 隔离性:多个事务并发访问时,事务之间是隔离的,一个事务执行不影响其他事务执行

  • 持久性:事务成功提交后,对数据的更改应该永久保存在数据库中,不会被回滚

事务的4种隔离级别

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

隔离级别 脏读 不可重复读 幻读
读未提交(Read Uncommitted) yes yes yes
读已提交(Read Committed) no yes yes
可重复读(Repeatable Read) no no yes
可串行化(Serializable) no no no

Read Uncommitted(读取未提交内容)

隔离级别中最低的一种,充许令外一个事务可以看到这个事务未提交的数据。如:事务A对数据做的修改,即使没有提交,对于事务B来说也是可见的。

在实际运用中会引起很多问题,因此一般不常用。这种隔离级别会产生脏读,不可重复读和幻像读。上述例子中就是脏读(Dirty Read),事务B读取到了事务A未提交的数据

Read Committed(读取提交内容)
此隔离级别下,保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。满足了隔离性的简单定义:一个事务只能看见已经提交事务所做的改变。

此时不会出现脏读的问题,事务A对数据做的修改,提交之后会对事务B可见。但会出现不可重复读(Nonrepeatable Read):在同一个事务中执行完全相同的select语句时可能看到不一样的结果。

简单来说就是事务A会多次读同一数据,如数据为1。在事务A执行第一次读数据后,事务B也访问数据1修改为了0并提交了事务,那么事务A执行第二次读数据时,读取到的就是0,两次读到的的数据就会不一样的。

不可重复读的重点是修改:
同样条件下,读取过的数据,再次读取发现结果不一致

Repeatable Read(可重读)
此隔离级别下,保证同一事务的多个实例在并发读取数据时,会看到同样的数据行。之前的例子中,事务B即便修改了同一数据1为0时,事务A多次读只会读取修改前的的数据1。

解决了不可重复读,但出现了幻读(Phantom Read):事务不是独立执行时发生的一种现象。多次读取一个范围内的记录发现结果不一致。

假设进行范围查询时,事务A第一次查询到10条记录为1的数据,事务A将所有为1的数据改为2,但还未提交时事务B插入了一条记录1的数据并提交了事务。那么事务A第二次读取时发现查询出11条,表中还存在没有修改的数据行,就好象发生了幻觉一样。

mysql中的Innodb 通过MVCC(多版本并发控制)来解决可重复读的情况下幻读的,但无法完全避免,还是需要配合锁机制来保证。

幻读的重点在于新增或者删除:
同样的条件,第 1 次和第 2 次读出来的记录数不一样

Serializable(可串行化)

这是最高最严格的隔离级别,它通过强制事务排序执行,使之不可能相互冲突,从而解决幻读问题。在这种隔离级别下,读取的每行数据都加锁,会导致大量的锁征用问题,大量的超时现象和锁竞争,性能最差。

什么情况适合使用事务

在进行多表或多sql组合操作时,为了保证结果达到一致性,需要用到事务。比如最典型的银行转账,需要确保一方金额的减少和一方金额的增加。

相关sql

查看隔离级别

-- 查看当前会话隔离级别
SELECT @@session.tx_isolation;
-- 查看系统当前隔离级别
SELECT @@tx_isolation;

设置隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL repeatable read;
-- SET SESSION TRANSACTION ISOLATION LEVEL 隔离级别(read uncommitted/read committed/repeatable read/serializable);

事务操作

-- 开始事务
START TRANSACTION;
-- 相关业务
SELECT * FROM xxx;
UPDATE xxx SET num =1 WHERE id = 1;
INSERT INTO xxx(id,num) VALUES(2,2);
-- 提交事务
COMMIT;
-- 或者回滚事务
-- ROLLBACK;

参考

https://www.cnblogs.com/phoebus0501/archive/2011/02/28/1966709.html
https://juejin.im/entry/5b835dfbf265da43531d0593
https://www.cnblogs.com/zhoujinyi/p/3437475.html
https://www.jianshu.com/p/ec52a27d3bf2
http://blog.sina.com.cn/s/blog_499740cb0100ugs7.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容