赞
踩
锁是计算机协调多个进程或线程并发访问某一资源的机制。
在数据库中,除传统的计算资源(如CPU、RAM、I/O等〉的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。
锁的分类
按照对数据的操作来分:读锁和写锁
读锁(共享锁):针对同一份数据,多个操作可以同时进行而不会互相影响.
写锁(排他锁):当前写操作没有完成前,它会阻断其他写锁和读锁
按照对数据操作的粒度分:表锁和行锁
开销、加锁速度、死锁、粒度、并发性能只能就具体应用的特点来说哪种锁更合适
表锁
表锁:偏向MyIsam存数引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率较高,并发度低
事务对表加了读锁时不能更新这个表
当前session不能查询其他没有锁定的表是因为还有一把锁没释放
写锁
简而言之,就是读锁会阻塞写,但是不会堵塞读。而写锁则会把读和写都堵塞。
行锁
行锁:偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高
InnoDb与MyIsam最大不同的两点,一是支持事务,而是采用了行级锁
索引失效的情况,行锁变表锁 一般存在varchar赋值缺少单引号的情况
锁的作用是为了满足事务隔离性,解决并发问题
InnoDB支持事务,MyIsam不支持事务
show engine innodb status
有一个模块叫事务
设置不自动提交事务,默认是自动提交的
set autocommit=0
InnoDB是给索引加锁
共享锁与独占锁均用于事务当中,随事务的结束而解除。
共享锁(share lock)
又称读锁,读取操作创建的锁。
一旦上锁,任何事务(包括当前事务)无法对其修改,其他事务可以并发读取数据,也可再对此数据再加共享锁
语法:SELECT … LOCK IN SHARE MODE;
排他锁(exclusive lock)
又称写锁,如果事务对数据A加上排他锁后,则其他事务不可并发读取数据,也不能再对A加任何类型的锁。获准排他锁的事务既能读数据,又能修改数据。
语法:SELECT … FOR UPDATE
意向锁
InnoDB所用的表级锁,其设计目的主要是为了在一个事务中揭示下一步将要被请求的锁的类型。
InnoDB中的两个表锁:
意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁
意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。
意向锁是InnoDB自动加的,不需要用户干预。
事务1要操作整张表,故锁住了整张表。那么事务2就不能对该表的单条记录或者元组加X锁或者S锁,去读取或者修改记录。
为了方便地检测表级锁和行级锁之间的冲突,于是引入了意向锁。
意向锁为了方便检测表级锁和行级锁之间的冲突,故在给一行记录加锁前,首先给该表加意向锁。也就是同时加意向锁和行级锁
1、意向锁之间彼此不会冲突,因为它们都只是“有意”,而不是真干,所以是可以兼容的。在加行锁之前,会使用意向锁判断是否冲突;
2、IX和X的关系等同于X和X之间的关系,为什么呢?因为事务获得了IX锁,接下来就有权利获取X锁,这样就会出现两个事务都获取X锁的情况,这和我们已知的X锁和X锁之间互斥是矛盾的;
3、S和IS、X和IS、IX和IS也可以由此推导出来。
共享锁和排它锁都是行锁,兼容是指对同一记录(ROW)锁的兼容性情况
为了支持在不同粒度上进行加锁操作,InnoDB存储引擎支持意向锁
通过锁定机制可以实现事务的隔离性要求,使得事务可以并发地工作。锁提高了并发,但是却会带来潜在的问题。不过好在因为事务隔离性的要求,锁只会带来三种问题,如果可以防止这三种情况的发生,那将不会产生并发异常。
脏读
在理解脏读(Dirty Read)之前,需要理解脏数据的概念。但是脏数据和之前所介绍的脏页完全是两种不同的概念。脏页指的是在缓冲池中已经被修改的页,但是还没有刷新到磁盘中,即数据库实例内存中的页和磁盘中的页的数据是不一致的,当然在刷新到磁盘之前,日志都已经被写入到了重做日志文件中。而所谓脏数据是指事务对缓冲池中行记录的修改,并且还没有被提交( commit)。
对于脏页的读取,是非常正常的。脏页是因为数据库实例内存和磁盘的异步造成的,这并不影响数据的一致性(或者说两者最终会达到一致性,即当脏页都刷回到磁盘)。并且因为脏页的刷新是异步的,不影响数据库的可用性,因此可以带来性能的提高。
脏数据却截然不同,脏数据是指未提交的数据,如果读到了脏数据,即一个事务可以读到另外一个事务中未提交的数据,则显然违反了数据库的隔离性。
不可重复读
不可重复读是指在一个事务内多次读取同数据集合。在这个事务还没有结束时,另外一个事务也访问该同一数据集合,并做了一些 DML操作。因此,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的情况,这种情况称为不可重复读。
不可重复读和脏读的区别是:脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据,但是其违反了数据库事务一致性的要求。可以通过下面一个例子来观察不可重复读的情况,如表6-16所示。
丢失更新
因为不同锁之间的兼容性关系,在有些时刻–个事务中的锁需要等待另一个事务中的锁释放它所占用的资源,这就是阻塞。阻塞并不是一件坏事,其是为了确保事务可以并发且正常地运行。
在InnoDB存储引擎中,参数innodb_lock_wait_timeout用来控制等待的时间(默认是50秒),innodb_rollback_on_timeout用来设定是否在等待超时时对进行中的事务进行回滚操作(默认是OFF,代表不回滚)。参数innodb_lock_wait_timeout是动态的,可以在MySQL数据库运行时进行调整:
锁升级(Lock Escalation)是指将当前锁的粒度降低。举例来说,数据库可以把一个表的1000个行锁升级为一个页锁,或者将页锁升级为表锁。如果在数据库的设计中认为锁是一种稀有资源,而且想避免锁的开销,那数据库中会频繁出现锁升级现象。
Microsoft sQL Server数据库的设计认为锁是一种稀有的资源,在适合的时候会自动地将行、键或分页锁升级为更粗粒度的表级锁。这种升级保护了系统资源,防止系统使用太多的内存来维护锁,在一定程度上提高了效率。
InnoDB存储引擎不存在锁升级的问题。因为其不是根据每个记录来产生行锁的,相反,其根据每个事务访问的每个页对锁进行管理的,采用的是位图的方式。因此不管一个事务锁住页中一个记录还是多个记录,其开销通常都是一致的。
1 若事务T对数据R已加X锁,则其他事务对数据R(D )?
可以加S锁不能加X锁
不能加S锁可以加X锁
可以加S锁也可以加X锁
不能加任何锁
S是共享锁,X是排他锁。
如果对一个事物加了X锁,则不能加任何锁。
如果对一个事物加了S锁,则只能加S锁不能加X锁。
s是共享锁,可读。 x是排他锁,可写。 加上x锁后其他事务不能操作指定数据。否则并发时会发生读脏数据,修改丢失,不可重复读,幻影读问题。这些并发不一致问题都是因为破坏了事务的隔离性,所以由锁来控制。
尚硅谷MySQL数据库高级,mysql优化,数据库优化
500分钟带你精通Mysql数据库(Mysql索引;Mysql锁机制;Mysql调优)
共享锁、排他锁与意向锁
MySQL 共享锁、排他锁、意向锁解析
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。