深入浅出划分数据库锁

1.数据库锁

    在数据库的四个特性ACID中,要想保持隔离性,在修改同一份数据的情况下,两个事务必须挨个执行以免出现冲突情况。而数据库有四种隔离级别(注意:不是所有数据库支持所有隔离级别)

隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
未提交读 (Read uncommitted)可能可能可能
已提交读(Read committed)不可能可能可能
可重复读(Repeatable read)不可能不可能可能
可串行化(Serializable )不可能不可能不可能

其中大多数数据库的默认隔离级别是Read committed。

Dirty reads:A事务可以读到B事务还未提交的数据。
Non-repeatable read:A事务读取一行数据,B事务后续修改了这行数据,A事务再次读取这行数据,结果得到的数据不同。
Phantom reads:A事务通过SELECT … WHERE得到一些行,B事务插入新行或者更新已有的行使得这些行满足A事务的WHERE条件,A事务再次SELECT … WHERE结果比上一次多了一些行。

关于不可重复读和幻读的区别,不可重复读重点在于update,而幻读的重点在于insert,和delete。二者最大的区别可以理解为如何通过锁机制来解决他们产生的问题。

2. 行级锁:排它锁和共享锁

排它锁,写锁:如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。
    在查询语句后面增加FOR UPDATE,Mysql会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。

共享锁,读锁:其他用户可以并发读取数据,但任何事务都不能对数据进行修改,如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。
    在查询语句后面增加LOCK IN SHARE MODE,Mysql会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。

表级锁在MyISAM和innoDB中都有用到,创建锁的开销小,不会出现死锁,由于锁定的是整张表,所以并发度低。当需要频繁对大部分数据做 GROUP BY 操作或者需要频繁扫描整个表时,推荐使用表级锁。

3. 表级锁:读锁和写锁

读锁
用法:LOCK TABLE table_name [ AS alias_name ] READ
    释放锁使用UNLOCK tables.可以为表使用别名,如果一旦使用别名在使用的时候也必须采用别名。成功申请读锁的前提是当前没有线程对该表使用写锁,否则该语句会被阻塞。申请读锁成功后,其他线程也可以对该表进行读操作,但不允许有线程对其进行写操作,就算是当前线程也不允许。当锁住了A表之后,就只能对A表进行读操作,对其他表进行读操作会出现错误(tablename was not locked with LOCK TABLES)

写锁
用法: LOCK TABLE table_name [AS alias_name] [ LOW_PRIORITY ] WRITE
    同样也可以使用别名,与读锁不同的是,写锁中可以指定锁的优先级。LOW_PRIORITY是一种比读锁更低优先级的锁,当多个线程同时申请多种锁(LOW_PRIORITY,READ,WRITE)时,LOW_PRIORITY的优先级最低。读锁申请成功的前提是没有线程对表加读锁和其他写锁,否则会被阻塞。

4. 乐观锁和悲观锁:

乐观锁:认为操作不会产生并发问题(不会有其他线程对数据进行修改)。
实现方法:

  1. 利用版本号
    取出记录时,获取当前version
    更新时,带上这个version
    执行更新时, set version = newVersion where version = oldVersion
    如果version不对,就更新失败
  2. 加入时间戳,在表中增加一个字段,更新提交时进行时间戳对比,一致就OK,否则就是版本冲突。

悲观锁:每次取数据时都认为其他线程会修改,所以都会加(悲观)锁。
应用实例:MySQL的读锁、写锁、行锁等
                 Java的synchronized关键字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值