数据库为什么需要锁机制?破坏数据库的一致性?有哪些锁机制?及 锁的种类【详细】

数据库多用户并发操作可能导致数据不一致,如脏读、不可重复读和幻读。为解决这些问题,数据库采用锁机制,包括行级锁、表级锁、悲观锁和乐观锁。行级锁开销大但并发高,表级锁开销小但可能导致死锁。悲观锁在读取数据时假设有并发修改,而乐观锁则在更新时检查是否被修改。事务隔离级别如READ_COMMITTED、REPEATABLE_READ等也有助于防止并发问题。此外,更新锁(updlock)和意向锁(Intent Locks)提高了并发性能。
摘要由CSDN通过智能技术生成

【为什么要锁】

    数据库是一个多用户使用的共享资源,比如一个用户表t_user,两个浏览器前面的人登录了同个一个账号,把电话号码改了。当多个用户并发地存取数
据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性(脏读,
不可重复读,幻读等),可能产生死锁。为了解决这个问题,加锁是一个非常重要的技术,对实现数据库并发控制是一个好的方案。简单说,当一个执行
sql语句的事务想要操作表记录之前,先向数据库发出请求,对你访问的记录集加锁,在这个事务释放这个锁之前,其他事务不能对这些数据进行更新操
作。
    
    【脏读,不可重复读,幻读等】

1. 脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然
后使用了这个数据。

2. 不可重复读 :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数
据之间,由于第二个事务的 修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称
为是不可重复读。例如,一个编辑人员两 次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始
读取不可重复。如果只有在作者全部完成编写后编辑人 员才可以读取文档,则可以避免该问题。

3. 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二
个事务也修改这个表中 的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好
象发生了幻觉一样。例如,一个编辑 人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添
加到该文档中。如果在编辑人员和生产部门完成对 原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。

补充 : 基于元数据的 Spring 声明性事务 :

Isolation 属性一共支持五种事务设置,具体介绍如下:

l          DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .

l          READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )

l          READ_COMMITTED  会出现不可重复读、幻读问题(锁定正在读取的行)

l          REPEATABLE_READ 会出幻读(锁定所读取的所有行)

l          SERIALIZABLE 保证所有的情况不会发生(锁表)

不可重复读的重点是修改 :
同样的条件 ,   你读取过的数据 ,   再次读取出来发现值不一样了
幻读的重点在于新增或者删除
同样的条件 ,   第 1 次和第 2 次读出来的记录数不一样

再想了想,其实你后面说的都没错,唯一的问题是“数据库不会处理并发操作”这个理解所引发的,数据库不是不会处理并发操作,如果它不会处理就没
有加锁机制 和事务隔离机制了,数据库的问题是在于它并不知道你的并发依赖关系,因此需要你告知它。数据库的并发处理控制并不依赖于Hibernate或
其它数据访问 层的实现机制,唯一需要的只是你要“告知它”哪里需要重点关照。

数据库默认情况下的事务管理是“已提交读取”,也就是说已经可以保证Select不会拿到脏数据(不会发生脏读----你理解错的地方);当然也可能你理
解错的脏读,脏读的意思是,事务B拿到了事务A中间状态的数据,而A后来把这个整个事务回滚了,那么事务B就相当于拿到了一个实际上根本不存在的脏
数据。

而不可重复读(幻读)和更新丢失的问题需要另外解决,这个你是说对了的;目前除了加锁(排他锁)和串行化隔离外,没有更好招数。

    【有哪些锁】

     锁包括行级锁、表级锁、悲观锁、乐观锁

     行级锁:一种它锁,防止另外事务修改此行;在使用以下语句时,Oracle会自动应用行级锁:INSERT、UPDATE、DELETE、SELECT … FOR UPDATE [OF
columns] [WAIT n | NOWAIT];SELECT … FOR UPDATE语句允许用户一次锁定多条记录进行更新.使用commit或者rollback释放锁。MySql的innodb存储引
擎默认是行级锁。特点:开锁大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。适合于有大量按索引更新少量不同数据
,同时又有并发查询的应用,如一些在线事务处理系统。
    表级锁:5种

   行共享 (ROW SHARE) – 禁止排他锁定表,与行排他类似,区别是别的事务还可以在此表上加任何排他锁。(除排他(exclusive)外)
   行排他(ROW EXCLUSIVE) – 禁止使用排他锁和共享锁,其他事务依然可以并发地对相同数据表执行查询,插入,更新,删除操作,或对表内数据行加
锁的操作,但不能有其他的排他锁(自身是可以的,没发现有什么用)
   共享锁(SHARE) - 锁定表,对记录只读不写,多个用户可以同时在同一个表上应用此锁,在表没有被任何DML操作时,多个事务都可加锁,但只有在仅
一个事务加锁的情况下只有此事务才能对表更新;当表已经被更新或者指定要更新时(select for update),任何事务都不能加此锁了。
   共享行排他(SHARE ROW EXCLUSIVE) – 比共享锁更多的限制,禁止使用共享锁及更高的锁,在表没有被任何DML操作时,只有一个事务可以加锁,可
以更新,书上说别的事务可以使用select for update锁定选中的数据行,可是实验后没被验证。
   排他(EXCLUSIVE) – 限制最强的表锁,仅允许其他用户查询该表的行。禁止修改和锁定表行级锁和表级锁是根据锁的粒度来区分的,行记录,表都是
资源,锁是作用在这些资源上的。如果粒度比较小(比如行级锁),可以增加系统的并发量但需要较大的系统开销,会影响到性能,出现死锁,,因为粒度
小则操作的锁的数量会增加;如果作用在表上,粒度大,开销小,维护的锁少,不会出现死锁,但是并发是相当昂贵的,因为锁定了整个表就限制了其它
事务对这个表中其他记录的访问。

   悲观锁:

   Pessimistic Lock正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守悲观态度,事务每次
去操作数据的时候都假设有其他事务会修改需要访问的数据,所以在访问之前都要求上锁,行锁,表锁等,读锁,写锁

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值