数据库并发访问、事务与锁的关系
2009-10-13 16:14
162 查看
数据库并发访问、事务与锁的关系
一、事务
I
:
事务的定义:
首先,让我们了解下什么是事务?事务是作为单个逻辑单元工作执行的一系列操作。可以是一条
sql
语句,也可以是多条
sql
语句
(
这是它的描述性定义
)
。
II
事务的特性:
1
)原子性
(Atomic)
:指整个数据库事务是不可分割的工作单位。
2
)一致性
(Consistency)
:指数据库事务不能破坏关系数据的完整性以及业务逻辑的一致性。
3
)
隔离性
(Isolation)
:指的是在并发环境中,当不同的事务同时操作相同的数据时,每个事务都有各自的完整数据空间。
4
)
持久性
(Durability)
:指的是只要事务成功结束,它对数据库所做的更改就必须永久保存下来。
数据库采用日志来保证事务的原子性,一致性和持久性,日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更改,使数据库退回到执行事务前的初始状态。
数据库使用锁机制来保证事务的隔离性,拥有各自独立的空间。
事务具有这四个特征是什么意思呢?是不是说作为一个事务必须具有这四个特性才成为事务或者就不是事务呢?本人是这样认为的,事务必须有原子性、一致性和持久性三个特征,而隔离性则根据实际的需要确定隔离的程度和隔离的级别(正是基于此才引出后面的事务的隔离级别)。
III
.
事务的隔离级别
1
、数据库事务的隔离级别:四种
那么事务的隔离级别与锁有什么关系呢?本人认为事务的隔离级别是通过锁的机制实现的,事务的隔离级别是数据库开发商根据业务逻辑的实际需要定义的一组锁的使用策略。当我们将数据库的隔离级别定义为某一级别后如仍不能满足要求,我们可以自定义
sql
的锁来覆盖事务隔离级别默认的锁机制。
读取未提交(
Read Uncommitted)
这是最低的事务隔离级别,读事务不会阻塞读事务和写事务,写事务也不会阻塞读事务,但是会阻塞写事务。这样造成的一个结果就是当一个写事务没有提交的时候,读事务照样可以读取,那么造成了脏读的现象。
读取已提交
(Read Committed)
采用此种隔离界别的时候,写事务就会阻塞读事务和写事务,但是读事务不会阻塞读事务和写事务,这样因为写事务会阻塞读取事务,那么从而读取事务就不能读到脏数据
,但是因为读事务不会阻塞其它的事务,这样还是会造成不可重复读的问题
可重复读(
Repeatable Read)
采用此种隔离级别,读事务会阻塞写事务
,但是读事务不会阻塞读事务,但是写事务会阻塞写事务和读事务
。因为读事务阻塞了写事务,这样以来就不会造成不可重复读的问题,但是这样还是不能避免幻影读问题。
序列化(
serializable)
此种隔离级别是最严格的隔离级别,如果设置成这个级别,那么就不会出现以上所有的问题(脏读,不可重复读,幻影读)。但是这样以来会极大的影响到我们系统的性能,因此我们应该避免设置成为这种隔离级别。
在实践中,我们一般采用读取已提交或者更低的事务隔离级别,配合各种并发访问控制策略来达到并发事务控制的目的。
二、锁
MySQL
的
InnoDB
有两种模式的行锁:
1
)共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
( Select * from table_name where ......lock in share
mode)
2
)排他锁:允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和
排他写锁。
(select * from
table_name where.....for update)
为了允许行锁和表锁共存,实现多粒度锁机制;同时还有两种内部使用的意向锁(都是表锁),分别为意向共享锁和意向排他锁。
InnoDB
行锁是通过给索引项加锁来实现的,即只有通过索引条件检索数据,
InnoDB
才使用行级锁,否则将使用表锁!
三、并发控制
当许多人试图同时修改数据库中的数据时,必须实现一个控制系统,使一个人所做的修改不会对其他人产生负面影响,这成为并发控制,并发控制有两种类型:
乐观并发控制和悲观并发控制。
乐观并发控制:
乐观锁:
基本思想:每次提交一个事务更新时,我们先看看要修改的东西从上次读取以后有没有被修改过,如果修改过,那么更新就会失败。
乐观锁其实并不会锁定任何记录,所以如果我们数据库的事务隔离级别设置为读取已提交或者更低的隔离界别,那么是不能避免不可重复读问题的(因为此时读事务不会阻塞其它事务),所以采用乐观锁的时候,系统应该要容许不可重复读问题的出现。
乐观锁的实现策略
版本
(Version)
字段:在我们的实体中增加一个版本控制字段,每次事务更新后就将版本字段的值加
1.
时间戳
(timestamps):
采取这种策略后,当每次要提交更新的时候就会将系统当前时间和修改时间。
悲观锁也就是上面讲到的我们认为的通常意义上的锁
。
以上有些是本人的一些愚见!大家感觉有什么不对的,欢迎指出愿和大家一起交流共同进步!
一、事务
I
:
事务的定义:
首先,让我们了解下什么是事务?事务是作为单个逻辑单元工作执行的一系列操作。可以是一条
sql
语句,也可以是多条
sql
语句
(
这是它的描述性定义
)
。
II
事务的特性:
1
)原子性
(Atomic)
:指整个数据库事务是不可分割的工作单位。
2
)一致性
(Consistency)
:指数据库事务不能破坏关系数据的完整性以及业务逻辑的一致性。
3
)
隔离性
(Isolation)
:指的是在并发环境中,当不同的事务同时操作相同的数据时,每个事务都有各自的完整数据空间。
4
)
持久性
(Durability)
:指的是只要事务成功结束,它对数据库所做的更改就必须永久保存下来。
数据库采用日志来保证事务的原子性,一致性和持久性,日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更改,使数据库退回到执行事务前的初始状态。
数据库使用锁机制来保证事务的隔离性,拥有各自独立的空间。
事务具有这四个特征是什么意思呢?是不是说作为一个事务必须具有这四个特性才成为事务或者就不是事务呢?本人是这样认为的,事务必须有原子性、一致性和持久性三个特征,而隔离性则根据实际的需要确定隔离的程度和隔离的级别(正是基于此才引出后面的事务的隔离级别)。
III
.
事务的隔离级别
1
、数据库事务的隔离级别:四种
隔离级别 | 脏读( Dirty Read ) | 写覆盖( Write Cover ) | 不可重复读( NonRepeatable Read ) | 幻读( Phantom Read ) |
读未提交( Read uncommitted ) | 可能 | 可能 | 可能 | 可能 |
读已提交( Read committed ) | 不可能 | 可能 | 可能 | 可能 |
可重复读( Repeatable read ) | 不可能 | 不可能 | 可能 | |
可串行化( Serializable ) | 不可能 | 不可能 | 不可能 |
sql
的锁来覆盖事务隔离级别默认的锁机制。
读取未提交(
Read Uncommitted)
这是最低的事务隔离级别,读事务不会阻塞读事务和写事务,写事务也不会阻塞读事务,但是会阻塞写事务。这样造成的一个结果就是当一个写事务没有提交的时候,读事务照样可以读取,那么造成了脏读的现象。
读取已提交
(Read Committed)
采用此种隔离界别的时候,写事务就会阻塞读事务和写事务,但是读事务不会阻塞读事务和写事务,这样因为写事务会阻塞读取事务,那么从而读取事务就不能读到脏数据
,但是因为读事务不会阻塞其它的事务,这样还是会造成不可重复读的问题
可重复读(
Repeatable Read)
采用此种隔离级别,读事务会阻塞写事务
,但是读事务不会阻塞读事务,但是写事务会阻塞写事务和读事务
。因为读事务阻塞了写事务,这样以来就不会造成不可重复读的问题,但是这样还是不能避免幻影读问题。
序列化(
serializable)
此种隔离级别是最严格的隔离级别,如果设置成这个级别,那么就不会出现以上所有的问题(脏读,不可重复读,幻影读)。但是这样以来会极大的影响到我们系统的性能,因此我们应该避免设置成为这种隔离级别。
在实践中,我们一般采用读取已提交或者更低的事务隔离级别,配合各种并发访问控制策略来达到并发事务控制的目的。
二、锁
MySQL
的
InnoDB
有两种模式的行锁:
1
)共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
( Select * from table_name where ......lock in share
mode)
2
)排他锁:允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和
排他写锁。
(select * from
table_name where.....for update)
为了允许行锁和表锁共存,实现多粒度锁机制;同时还有两种内部使用的意向锁(都是表锁),分别为意向共享锁和意向排他锁。
InnoDB
行锁是通过给索引项加锁来实现的,即只有通过索引条件检索数据,
InnoDB
才使用行级锁,否则将使用表锁!
三、并发控制
当许多人试图同时修改数据库中的数据时,必须实现一个控制系统,使一个人所做的修改不会对其他人产生负面影响,这成为并发控制,并发控制有两种类型:
乐观并发控制和悲观并发控制。
乐观并发控制:
乐观锁:
基本思想:每次提交一个事务更新时,我们先看看要修改的东西从上次读取以后有没有被修改过,如果修改过,那么更新就会失败。
乐观锁其实并不会锁定任何记录,所以如果我们数据库的事务隔离级别设置为读取已提交或者更低的隔离界别,那么是不能避免不可重复读问题的(因为此时读事务不会阻塞其它事务),所以采用乐观锁的时候,系统应该要容许不可重复读问题的出现。
乐观锁的实现策略
版本
(Version)
字段:在我们的实体中增加一个版本控制字段,每次事务更新后就将版本字段的值加
1.
时间戳
(timestamps):
采取这种策略后,当每次要提交更新的时候就会将系统当前时间和修改时间。
悲观锁也就是上面讲到的我们认为的通常意义上的锁
。
以上有些是本人的一些愚见!大家感觉有什么不对的,欢迎指出愿和大家一起交流共同进步!
相关文章推荐
- 数据库并发访问、事务与锁的关系
- 数据库并发访问、事务与锁的关系
- spring.net 分布式事务 实现方式 多数据库并发访问下 服务层 事务管理 .net下事务管理
- 如何设计数据表、解决数据库并发访问瓶颈、数据库事务----阿里巴巴2015校招研发在线
- 关系数据库的事务隔离、锁定与并发控制
- 数据库并发访问、事务与锁、脏读、不可重复读、幻影读
- Oracle 数据库中不同事务并发访问的问题
- 利用Memcache解决数据库高并发访问的瓶颈问题
- Hibernate--多事务并发访问控制
- 使用ab.exe监测100个并发/100次请求情况下同步/异步访问数据库的性能差异
- 数据库并发事务存在的问题(脏读、不可重复读、幻读等)
- [数据库]事务、并发、数据库锁
- DDD:在基于关系数据库的领域,聚合的边界等于并发管理的边界。
- 数据库的事务、事务并发以及隔离级别
- 数据库--事务(定义、基本特征、并发问题)
- 事务特性,事务的隔离级别,并发事务可能出现的问题,spring事务 数据库锁
- 数据库的三大并发事务问题与四大隔离级别
- [学习笔记]在数据库层面应对并发访问产生的问题
- 数据库事务并发有关问题