事务的隔离 transaction isolation

本文深入解析了四种事务隔离级别:Serializable、Read Committed、Repeatable Read 和 Read Uncommitted,在并发场景下如何避免脏读、不可重复读、幻读及序列化异常等现象。通过具体的例子说明了每种隔离级别对这些问题的解决程度。

总共有4钟transaction isolation. Serializable level的transaction,并发运行和挨个执行的结果是一样的。并发的transaction会产生缺陷(phenomena)。Serialization level 的transaction不会有这些缺陷(phenomena)。

 

在不同transaction levels 中被消灭的缺陷(phenomena)

sex

name

male

李雷

female

韩梅梅

Dirty read: 多条并发transaction中,一个transaction中的sql读取了另一个transaction未提交(committed)的数据。

脏读:

transaction1

transaction2

Begin:

Begin:

Select * from user where sex=’male’;

查出:李雷

 

 

Insert into user (‘Jack’,  ‘male’)

Select * from user where sex=’male’;

查出:李雷和 Jack

 

 

commit

Nonrepeatable read: 在一个transaction中,一条数据被先后读了两次。由于这中间另外一个transaction修改了这条数据,并提交了,导致第二次读出来的数据和第一次不一样。

transaction1

transaction2

Begin:

Begin:

Select * from user where sex=’male’;

查出:李雷

 

 

Insert into user (‘Jack’,  ‘male’)

 

commit

Select * from user where sex=’male’;

查出:李雷和 Jack

 

 

 

Phantom read: 在一个transaction中,一条查询sql执行了两次。由于中间有另一个transaction提交了数据,导致两次查出来的数据集不同。

transaction1

transaction2

Begin:

Begin:

Select * from user where sex=’male’;

查出:李雷

 

 

Insert into user (‘Jack’,  ‘male’)

 

commit

Select * from user where sex=’male’;

查出:李雷和 Jack

 

 

 

Serialization anomaly:多个transaction并发执行的结果和挨个执行的结果不同。

transaction1

transaction2

Begin:

Begin:

Select * from user where sex=’male’;

查出:李雷

 

 

Insert into user (‘Jack’,  ‘male’)

 

commit

Insert into user (‘MR李雷,  ‘male’)

必须要有这条插入语句,因为只读事务不会混滚

 

Commit;

提交的时候会回滚,因为查询语句在事务的中途失效了。

 

 

 

不同的事务隔离级别对应解决的问题

Isolation level

Dirty read

Nonrepeatable read

Read phantom

Serialization anomaly

Read uncommitted

×(only in PostgreSQL)

 

 

 

Read committed

×

 

 

 

Repeatable read

×

×

×(only in PostgreSQL)

 

serialization

×

×

×

×

提醒

Sequence的变化会立即同步给并发的transaction,并且不会因为某一个transaction回滚而回滚squence。同理还有serial。

`SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE` 是一条用于设置事务隔离级别的 SQL 语句。 ### 含义 该语句将当前会话的事务隔离级别设置为 `SERIALIZABLE`(可串行化)。SQL 标准定义了 4 类隔离级别,用来限定事务内外的哪些改变是可见的,哪些是不可见的,而 `SERIALIZABLE` 是其中隔离级别最高的。在 `SERIALIZABLE` 隔离级别下,事务之间是串行执行的,即一个事务执行完成后,另一个事务才能开始执行,这样可以避免脏读、不可重复读和幻读等问题,但同时也会降低系统的并发处理能力,因为事务要排队等待执行,会增加系统开销 [^1][^4]。 ### 用法 该语句的使用场景通常是在需要确保数据的一致性和完整性,对并发性能要求不高的情况下。以下是使用该语句的示例步骤: 1. **设置隔离级别**:执行 `SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;` 语句,将当前会话的事务隔离级别设置为 `SERIALIZABLE`。 ```sql SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; ``` 2. **开启事务**:使用 `BEGIN` 或 `START TRANSACTION` 语句开启一个新的事务。 ```sql BEGIN; ``` 3. **执行 SQL 操作**:在事务中执行需要的 SQL 操作,如查询、插入、更新或删除数据。 ```sql SELECT * FROM your_table; ``` 4. **提交或回滚事务**:根据操作结果,使用 `COMMIT` 语句提交事务,使操作生效;或者使用 `ROLLBACK` 语句回滚事务,撤销操作。 ```sql COMMIT; -- 或者 ROLLBACK; ``` 以下是一个完整的示例,展示了如何在客户端使用 `SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE` 语句: ```sql -- 设置当前会话的事务隔离级别为 SERIALIZABLE SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- 开启事务 BEGIN; -- 执行查询操作 SELECT * FROM u WHERE id='5'; -- 提交事务 COMMIT; ``` ### 并发场景示例 在并发场景下,当多个客户端同时设置隔离级别为 `SERIALIZABLE` 时,会出现事务排队等待的情况。例如,有两个客户端: ```sql -- 客户端 1 -- 设置隔离级别 SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- 开启事务 BEGIN; -- 查询操作 SELECT * FROM u WHERE id='5'; -- 客户端 2 -- 设置隔离级别 SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- 开启事务 BEGIN; -- 插入操作,会因为客户端 1 的事务未完成而等待 INSERT INTO u VALUES(5,'zb'); ``` 在这个例子中,客户端 2 的插入操作会等待客户端 1 的事务完成,否则会出现 `Lock wait timeout exceeded; try restarting transaction` 错误 [^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值