数据库的隔离级别与对应的锁机制

读未提交(Read Uncommitted)的锁机制:

       在事务开始以后,遇到SQL的CRUD语句时,如果是读操作,就给该行数据一个S锁,如果是写操作,给要准备写操作的这一行数据加一个X锁。读或写完就立马释放掉锁。
在其他事务修改该行数据的时候,不让其他进程对该行数据有任何操作(不能加X和S锁)。而读该行数据的时候,其他进程不能更改,但可以读(可以加S锁但不能加X锁)。最后commit/rollback。

读未提交不能解决:脏读,不可重复读,幻读。下面是一个脏读的例子。

 Transaction ATransaction B
T1

mysql> use sys;
Database changed
mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@TX_ISOLATION;
+------------------+
| @@TX_ISOLATION |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> use sys;
Database changed
mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@TX_ISOLATION;
+------------------+
| @@TX_ISOLATION |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

 T2

mysql> select * from test;
+----+-------+
| id | price |
+----+-------+
| 1  | 100 |
+----+-------+
1 row in set (0.01 sec)

 
 T3 

mysql> update test set price = 110 where id = 1;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0

 T4

mysql> select * from test;
+----+-------+
| id | price |
+----+-------+
| 1  | 110 |
+----+-------+
1 row in set (0.00 sec)

【说明】出现脏读

 
 T5 

mysql> rollback;
Query OK, 0 rows affected (0.10 sec)

 T6

mysql> select * from test;
+----+-------+
| id | price |
+----+-------+
| 1  | 100 |
+----+-------+
1 row in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

读提交(Read committed)的锁机制:

       读未提交会出现脏读。只需调整锁的位置。之前是只要写操作完该数据就立马释放掉X锁,现在是把释放X锁的位置调整到事务提交之后。此时在事务提交前,其他进程是无法对该行数据进行读取和修改的。

       既然说此种隔离性是在事务提交后才释放锁,但是你会发现有些数据库,在试验过程中,在该数据未提交前,另一个事务也是仍然可以读取的。原因就是它们使用了一个并发版本控制机制(MVCC)。为了提高系统的并发量,在事务未提交前,虽然事务内操作的数据是锁定状态,但是另一个事务仍然可以读取(但不能修改)。比如对于数据项A,它的数据版本为A1->A2->A3,最新版本是A3。如果事务T1在读写数据项A时,A1和A2已提交的,事务T2正在修改A3,那么A3可以被提交,也可能被回滚。在使用锁协议时,事务X要等待Y结束,才能判断是否读到A3。在MVCC中,事务X可以读取已经提交的A2,而不必等待A3。这么操作逻辑上是合理的,因为事务T1读到了一个最新的已经提交数据,这不会带来数据不一致,也避免了读写操作的冲突等待。在上面的情况中,X可以读到A2,如果X要写A怎么办?从逻辑上说,A3不确定是提交还是回滚,X必须等待Y结束,才能开始写操作。

读提交解决了脏读问题,但是不能解决:不可重复读,幻读。下面是几个例子,分别验证了读提交避免了脏读,但是出现了不可重复读,以及MVCC中可以读到前一个版本的快照和不能同时写的操作。

 

重复读(Repeatable Read)的锁机制:

    理想的工业标准是,在读提交的基础上继续调整锁的位置,之前是只要读操作完该数据就立马释放掉S锁,现在将其调整到事务结束后再释放S锁。即在读的时候不允许其他事务修改这条记录。

MySQL默认为这个隔离级别,可以防止脏读,不可重复读,但是不能防止幻读。

但是,在MVCC机制下,为了使这种隔离级别的性能提高,MySQL InnoDB在重复读(Repeatable Read)的锁机制上也做了相应的处理

具体请看下节内容:

 

 

序列化(Serializable):

不再赘述。在该级别下,事务顺序串行执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

转载于:https://www.cnblogs.com/storml/p/7839055.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值