数据库中的锁与事务

原文地址: CoderGO : 数据库中的锁与事务

引言

什么事事务?事务是一组原子性的SQL语句,这组语句要么全部成功,要么发生失败时全部不执行。一个良好的支持事务数据库系统必须支持如下4个特性:

  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔离性(isolation)
  • 持久性(durability)

事务中的隔离性在数据库系统中一般采用锁来实现,针对不同的隔离级别有不同的隔离策略,要想在性能和隔离性中作出均衡,在数据库系统种是一个难点。

一、事务的特征

一个好的事务数据库,必须具备ACID特征:

  • 原子性:
    一个事务必须是不可分割的最小工作单元,整个事务中所有操作要么全部提交成功,或者全部失败回滚。
  • 一致性:
    数据库总是从一个一致性的状态转换到另一个一致性的状态,事务不会破坏数据库的完整性和业务上的一致性。
  • 隔离性:
    一个事务所做的修改在最终提交前,对其他事务是不可见的。在并发时,每个事务都拥有自己的工作和数据空间,不会相互干扰。
  • 持久性:
    一旦事务提交,所做的修改会永久保存到数据库系统中,及时系统崩溃,修改的数据也不会丢失。

数据库系统采用日志来保证事物的原子性,一致性和持久性。日志保存了用户对数据库所做的更改,如果事务在执行过程中发生错误,则数据库可以根据日志所记录的更改过程,回退到事务开始执行前的状态。

隔离性有多个级别(未提交读,提交读,可重复读,可串行化),一般数据库采用锁机制实现事务的隔离性,并达到某个级别,此时就可以保证事务的隔离性。当多个事务同时更新数据库中的相同数据时,只允许持有锁的事务才能更改数据,其他事务必须等待获得锁后才能更改数据。

二、隔离级别

SQL标准中定义了四种隔离级别,每种级别规定了一个事务中所做的修改,哪些时事务间可见,那些事事务内可见,哪些不可见,低级别的隔离往往具有更高的并发性能,开销也低。

  • 未提交读:
    事务中的修改,没有提交,其他事务也可以读取未提交的数据,也叫脏读。实际中一般很少用。
  • 提交读:
    大多数数据库系统的默认隔离级别是提交读,但MySQL不是。提交读满足隔离性的简单定义:一个事务开始时,只能看见已经提交的事务所做的修改。这个级别可能会在事务开启前后两次读到的数据不一致,又称为不可重复读
  • 可重复读:
    可重复读解决了脏读和不可重复读的问题,保证在同一个事务中多次读取 同样的数据结果是一致的(即使有其他事务在此期间对该记录进行了修改)。仍存在幻读的问题:当某个事务在读取某范围 内的记录时,另一个事务在该范围内插入了新的记录,之前的食物重新读取该范围时,会产生新的记录(幻行)。
    在MySQL中默认隔离级别为可重复读,并且InnoDB使用MVCC(多版本并发控制)解决了幻读的问题。
  • 可串行化:
    最高的隔离级别。强制事务串行化,避免了幻读的问题。会在读取的每一行数据上加锁,会导致锁争用问题,实际很少使用。

ANSI SQL隔离级别

隔离级别脏读可能性不可重复读可能性幻读可能性加锁读
read uncommittedYesYesYesNo
cead committedNoYesYesNo
repedtabel readNONoYesNo
serializableNoNoNoYes

三、数据库中的锁

在数据库中多个SQL语句在同一时刻修改数据,会产生并发控制的问题,如果不加以控制,就会造成事务中的隔离性被破坏,引起不可预知的错误。

1.锁的类型

实现并发访问可以采用两种类型的锁,读锁/共享锁和写锁/排它锁:

  • 读锁/共享锁:共享的锁,多个客户端可以同时读取一个资源,互补干扰。
  • 写锁/排它锁:一个锁会阻塞其他的写锁和读锁,确保一个时刻只有一个客户端对通过一个数据进行修改写入。

在数据库系统中,锁对于用户时透明的,一般情况下,用户不用关心什么时候使用锁。

2.锁的粒度

锁定的数据量越少,系统的并发性能越好,因此数据库的锁只对需要修改的数据进行锁定。但加锁也需要消耗资源,锁的各种操作,包括获得,检查锁状态和释放锁都会增加系统开销。因此有必要在锁的开销和数据安全性之间平衡。一般情况下,数据库系统通常采用行级锁,即锁定修改的数据行。

在MySQL中提供了多种选择,每种引擎均会实现自己的锁策略和粒度。下面是两个最重要的锁策略。

  • 表锁
    是开销比较小的策略,会锁定整张表。用户对表进行写操作,需要先获得锁,并且会阻塞用户对该表的所有读操作。
    数据库中对表进行修改,如alter table会使用到表锁,会锁定整张表,因此此类操作在数据库中应该谨慎使用。
  • 行锁
    行锁可以高效的支持并发,当然锁开销也是最大。MySQL的InnoDB引擎中实现了行锁,在用户写数据时,只锁定需要操作的数据行,相比于表锁并发度更好。

  1. 《高性能MySQL》
  2. 《精通Hibernate:Java对象持久化技术详解》
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值