关于不同隔离级别下锁机制的研究

众所周之,隔离级别分为:

  1.       Read Uncommited:可以读取提交的记录
  2.      ReadCommitted:仅读到提交的数据,会产生幻读现象
  3.     Repeatable Read :对读取到的数据加锁,并对读取的范围加锁,不存在幻读现象
  4.     Serializable:读加读锁写加写锁,串行执行

 

情况一:主键(where  主键=???)

Read Committed隔离级别

show create table key_id;

+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------+

| Table | Create Table                                                                                                                                            |

+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------+

| key_id | CREATE TABLE `key_id` (

`id` char(128) NOT NULL DEFAULT ‘‘,

`data` char(128) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

mysql> select * from key_id;

+----+------+

| id | data |

+----+------+

| 10 | bb  |

| 2 | b    |

| 3 | c    |

| 4 | a    |

| 8 | cd   |

+----+------+

第一个事务

start transaction ;

Query OK, 0 rows affected (0.00 sec)

mysql> delete from key_id where id=’3’

-> ;

Query OK, 1 row affected (0.00 sec)

第二个事务

update key_id set data=‘cc‘ where id=’3’;

ERROR 1205 (HY000): Lock wait timeoutexceeded; try restarting transaction

update key_id set data=‘cc‘ where id=’4’;

Query OK, 1 row affected (0.01 sec)

Id=3的key锁住了,其他的列可以更新。

#####记录行锁

Repeatable Read 隔离级别

事务1

mysql> start transaction ;

Query OK, 0 rows affected (0.00 sec)

mysql> update key_id set data=‘kl‘ whereid=‘8‘;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

事务2

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> update key_id set data=‘kk‘ whereid=‘4‘;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

mysql> delete from key_id where id=‘4‘;

Query OK, 1 row affected (0.00 sec)

mysql> delete from key_id where id=‘8‘;

^CCtrl-C -- sending "KILL QUERY63" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

mysql> insert into no_index values(‘15‘,‘b‘);

ERROR 1136 (21S01): Column count doesn‘tmatch value count at row 1

mysql> insert into key_id values(‘15‘,‘b‘);

Query OK, 1 row affected (0.00 sec)

#####说明where  主键=???或者是Insert,是行锁,RepeatableReadRead Committed没有区别,并且同一事务内操作不会互锁。

 

情况二:没有索引

CREATE TABLE `no_index` (

`id` int(11) DEFAULT NULL,

`fir` varchar(128) DEFAULT NULL,

`sec` varchar(128) DEFAULT NULL

)

mysql> select * from no_index;

+------+------+------+

| id  | fir  | sec  |

+------+------+------+

|   1 |  a   | aa  |

|   2 |  b   | bb  |

|   3 | c    | cc   |

+------+------+------+

Read Committed

事务1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> delete from  no_index where id=1;

事务2 delete其他行被锁住

mysql> start transaction;

mysql> delete from no_index where id=3;

Ctrl-C -- sending "KILL QUERY707" to server ...

Ctrl-C -- query aborted.

事务1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> delete from  no_index where id=1;

事务2 updateinsert其他行没有被锁

mysql> update no_index set id=30  where id=3;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1  Changed: 1 Warnings: 0

mysql> insert into no_index values(‘12‘,‘a‘,‘b‘);

Query OK, 1 row affected (0.00 sec)

#####在无索引情况下updateinsertdeleteRepeatable Read)是全表锁。然而当其他事务运用update,insert操作时,会触发semi-consistent产生优化,全表锁降为行锁,其他事务运用delete操作仍然被全表锁。

 

Repeatable Read 隔离级别

事务1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> update no_index set id=10where id=1;

 

事务2updateinsertdelete操作都被锁住

mysql> insert into no_index values(‘14‘,‘a‘,‘b‘);

Ctrl-C -- sending "KILL QUERY707" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

mysql> delete from no_index whereid=3;

Ctrl-C -- sending "KILL QUERY707" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

mysql> update no_index set id=30  where id=3;

Ctrl-C -- sending "KILL QUERY707" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

 

 

######可以看到在无索引情况下Repeatable Read是全表锁,其他事务运用update,insert操作时不触及优化。

第三情况:普通索引(where  索引=???)

CREATE TABLE `index_id` (

`id` int(11) DEFAULT NULL,

`fir` varchar(128) DEFAULT NULL,

`sec` varchar(128) DEFAULT NULL,

KEY`id` (`id`)

)

READ-COMMITTED

事务1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> delete from  index_id where id=1;

Query OK, 1 row affected (0.00 sec)

事务2

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> update index_id set id=1  where id=3;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

#####READ-COMMITTED说明where  索引=???或者是Insert时,是行锁。

repeatable-read

事务1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> delete from  index_id where id=1;

Query OK, 1 row affected (0.01 sec)

事务2 id不能更新为1,因为事务1id=1是更新行,id=1有间隙锁。更新为其他数字则不受影响

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> update index_id set id=10  where id=3;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

mysql> update index_id set id=1  where id=3;

Ctrl-C -- sending "KILL QUERY715" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

#####可以看到repeatable-read下事务1删除id这行时,产生行锁外还产生间隙锁,使得被更新的这条记录不会产生幻读现象。那为什么在无索引或者唯一索引时不会有间隙锁的产生?是因为唯一索引时保证了被更新的那条记录只有一条不会产生幻读。无索引情况下,整个表已经被全部锁住了,所以不会产生幻读现象

时间: 2024-10-12 04:14:52

关于不同隔离级别下锁机制的研究的相关文章

事务的传播行为,隔离级别以及锁机制

脏读,不可重复读和幻读. 脏读:读到未提交(uncommited)的数据 不可重复读:多次查询中(提交插入数据的事务) 幻读:在修改事务后(提交了一个添加的事务),之后查询数据以为出现幻觉 事务的隔离级别: read_uncommitted 最低的隔离级别 有脏读,不可重复读和幻读. read_committed 看到已提交的数据 存在不可重复读和幻像读. 支持sqlsever repeatable_read 存在幻读 .支持mysql serializable 防止脏读,不可重复读外,还避免了

mysql 开发进阶篇系列 12 锁问题(隔离级别下锁的差异)

1. innodb在不同隔离级别下的一致性读及锁的差异 不同的隔离级别下,innodb处理sql 时采用的一致性读策略和需要的锁是不同的,同时,数据恢复和复制机制的特点,也对一些sql的一致性读策略和锁策略有很大影响.对于许多sql, 隔离级别越高,innodb给记录集的锁就越严格(龙其是使用范围条件的时候),产生的锁冲突的可能性也就越高,对并发性事务处理性能的影响也就越大.因此,在应用中,应该尽量使用较低的隔离级别,减少锁争用.通常使用Read Commited隔离级别就足够了, 对于一些确实

数据库事务、事务隔离级别以及锁机制详解

以下主要以MySQL(InnoDB引擎)数据库为讨论背景,纯属个人学习总结,不对的地方还请指出! 什么是事务? 事务是作为一个逻辑单元执行的一系列操作,要么一起成功,要么一起失败.一个逻辑工作单元必须有四个属性,称为 ACID(原子性.致性.隔离性和持久性)属性,只有这样才能成为一个事务. 数据库事物的四大特性(ACID): 1)原子性:(Atomicity) 务必须是原子工作单元:对于其数据修改,要么全都执行,要么全都不执行. 2)一致性:(Consistency) 事务在完成时,必须使所有的

Read Commited 隔离级别下锁情况(MVCC实现原理)

如何通过单纯加锁实现RC隔离级别的隔离效果? 对InnoDB引擎下的mysql数据库支持行级锁,通过对事务访问时增加排他锁(X锁)可以防止其他事务的访问,只有在该事务锁提交也就是commit后才可以访问,避免脏读产生.但是在多读的场景下,一个事务假如在进行update操作,后面有许多请求都想要单纯进行读操作(普通的SELECT语句),可是因为有锁的存在只能进行等待.该方法在多读的并发环境下效率大大降低. 真实情况下由于InnoDB在RC和RR隔离级别下使用了MVCC机制,实现了一致性非阻塞读,提

RR隔离级别下锁情况(探究gap锁和行锁)

!!!我的数据库演示版本为5.5,以后会追加最新数据库的演示版本 间隙锁(GAP Lock)时InnoDB在可重复读下的隔离级别下为了解决幻读问题引入的锁机制.幻读存在的问题是因为在新增或者更新时如果进行查询,会出现不一致的现象,这时单纯的使用行锁无法满足我们的需求,我们需要对一定范围的数据加锁,防止幻读. 可重复读隔离级别就是数据库通过行锁和间隙锁(不要搞混gap lock和next-key lock)共同组成来实现的,在网上抄了一下加锁的规则,然后自己进行一下验证: 1.加锁的基本单位是(n

SqlServer中的事务隔离级别、锁机制

事务 作用:用来执行一连串的动作,并且保证所有动作要么都执行.要么都不执行. 属性:原子行.一致性.隔离性.持久性 锁 作用:SqlServer使用锁来实施事务隔离属性. 阻塞 定义:如果一个事务持有一数据资源的锁,而另一事务请求相同资源的不兼容的锁,则新锁的请求将被阻塞. 默认情况下,被阻塞的请求会一直等待,直到原来的事务释放相关的锁. 事务的隔离级别 可设置的有6个(从上往下 隔离级别越来越高): 1.read uncommitted 2.read committed 3.repeatabl

MySQL事务及实现、隔离级别及锁与优化

事务  事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.事务是逻辑上的一组操作,要么都执行,要么都不执行. ACID简介 原子性(Atomicity).一致性(Correspondence).隔离性(Isolation).持久性(Durability). (1)原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节.事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一

浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题

原文:浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题 本文出处:http://www.cnblogs.com/wy123/p/7501261.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他) 数据库在处理并发事物的过程中,在不同的隔离级别下有不同的锁表现,在非可序列化隔离级别下,存在着脏读,不可重复读,丢失更新,幻读等情况.本文不讨论脏读和不可重复读以及丢失更新的情形,仅讨论幻读,幻

Innodb中的事务隔离级别和锁的关系

前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. #一次封锁or两段锁? 因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道