InnoDB行锁实现方式
InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
在进一步分析Hadoop相关的分布式事务和锁的机制前,有必要先整理和对比分析一下RDBMS领域最红的两大领军人物
Oracle VS Mysql
1:事务隔离级别
oracle默认为Read committed
Mysql的InnoDB默认为Repeatable Read.
2:锁类别
oracle
内部级封锁(对外不公布,无法了解)
DDL锁(对数据字典、词法分析封锁)
细分:(1)、字典操作锁:用于对字典操作时,锁住数据字典,此封锁是独占的,从而保护任何一个时刻仅能对一个字典操作。
(2)、字典定义锁:用于防止在进行字典操作时又进行语法分析,这样可以避免在查询字典的同时改动某个表的结构。
(3)、表定义锁:用于 一个 SQL 语句正当访问某个表时,防止字典中与该表有关的项目被修改。
DML锁(对数据控制操作进行锁定)
细分包括:
(1)共享锁 (2)独占锁 (3)共享更新锁
另外:Oracle的所在另外一个层面还可以划分为两大类
悲观锁:
锁在用户修改之前就发挥作用:
Select ..for update ( nowait)
Select * from tab1 for update
乐观锁:
乐观的认为数据在 select 出来到 update 进取并提交的这段时间数据不会被更改。这里面有一种潜在的危险就是由于被选出的结果集并没有被锁定,是存在一种可能被其他用户更改的可能。因此Oracle 仍然建议是用悲观封锁,因为这样会更安全。
myql
表级锁定(系统缺省,MyISAM,Memory,CSV)
分为:读锁、写锁
行级锁定(InnoDB,NDB Cluster)
独占锁、共享锁、意向独占锁、意向共享锁,InnoDB由于实现机制方式,具有【间隙锁】
页级锁定(Berkeley DB)
上述所的开销如何呢,对应的适合场景如何?
规则:
1:锁的对象粒度跟并行度成反比
2:所得粒度大小跟所需的成本成反比
所以可以基本得出:
a:独占锁更安全,但是并发性低
b:乐观锁,支持并发更高,但是需要业务来适应锁出现的问题
c:行锁粒度更小,支持更小的并发性,但是对应的资源消耗也必将高
注意Oracle的锁机制跟Mysql的类似点
DML 锁的三种封锁方式:
( 1 )、共享封锁方式( SHARE )
( 2 )、独占封锁方式( EXCLUSIVE )
( 3 )、共享更新封锁( SHARE UPDATE )
其中 SHARE , EXCLUSIVE 用于表封锁, SHARE UPDATE 用于行封锁。
注意:在Mysql中
共享锁在行级别上应该也可以支持
独占锁在列上也应该可以支持
另外一点:Oracle需要区分另外几类锁的规则:
Oracle的TX锁(行级锁、事务锁)
TX的本义是Transaction(事务),当一个事务第一次执行数据更改(Insert、Update、Delete)或使用SELECT… FOR UPDATE语句进行查询时,它即获得一个TX(事务)锁,直至该事务结束(执行COMMIT或ROLLBACK操作)时,该锁才被释放。所以,一个TX锁,可以对应多个被该事务锁定的数据行。
TM锁(表级锁)
意向锁:
表是由行组成的,当我们向某个表加锁时,一方面需要检查该锁的申请是否与原有的表级锁相容;
另一方面,还要检查该锁是否与表中的每一行上的锁相容。
比如一个事务要在一个表上加S锁,如果表中的一行已被另外的事务加了X锁,那么该锁的申请也应被阻塞。
如果表中的数据很多,逐行检查锁标志的开销将很大,系统的性能将会受到影响。
为了解决这个问题,可以在表级引入新的锁类型来表示其所属行的加锁情况,这就引出了“意向锁”的概念。
意向锁的含义是如果对一个结点加意向锁,则说明该结点的下层结点正在被加锁;对任一结点加锁时,必须先对它的上层结点加意向锁。
如:对表中的任一行加锁时,必须先对它所在的表加意向锁,然后再对该行加锁。这样一来,事务对表加锁时,就不再需要检查表中每行记录的锁标志位了,系统效率得以大大提高。
意向锁的类型:
由两种基本的锁类型(S锁、X锁),可以自然地派生出两种意向锁:
意向共享锁(Intent Share Lock,简称IS锁):如果要对一个数据库对象加S锁,首先要对其上级结点加IS锁,表示它的后裔结点拟(意向)加S锁;
意向排它锁(Intent Exclusive Lock,简称IX锁):如果要对一个数据库对象加X锁,首先要对其上级结点加IX锁,表示它的后裔结点拟(意向)加X锁。
基本的锁类型(S、X)与意向锁类型(IS、IX)之间还可以组合出新的锁类型,理论上可以组合出4种,
即:S+IS,S+IX,X+IS,X+IX,但稍加分析不难看出,实际上只有S+IX有新的意义,其它三种组合都没有使锁的强度得到提高(即:S+IS=S,X+IS=X,X+IX=X,这里的“=”指锁的强度相同)。所谓锁的强度是指对其它锁的排斥程度。
共享意向排它锁(Shared Intent Exclusive Lock,简称SIX锁) :如果对一个数据库对象加SIX锁,表示对它加S锁,再加IX锁,即SIX=S+IX。例如:事务对某个表加SIX锁,则表示该事务要读整个表(所以要对该表加S锁),同时会更新个别行(所以要对该表加IX锁)。
貌似看起来比较乱,差异就在于两者对锁的实现具体技术和设计理念的差异:
Oracle对锁的设计更加极致和全面,实现技术方面更加全面,但是不公开细节
Mysql明确支持2到3种,而且不同的存储引擎各有所专场,虽然不如oracle的全面,但是灵活运用还是可以满足需要,并且可能超出想象。
查看锁的方式:
oracle:
1.查哪个过程被锁
查V$DB_OBJECT_CACHE视图:
SELECT * FROM V$DB_OBJECT_CACHE WHERE OWNER=''过程的所属用户'' AND LOCKS!=''0'';
2. 查是哪一个SID,通过SID可知道是哪个SESSION.
查V$ACCESS视图:
SELECT * FROM V$ACCESS WHERE OWNER=''过程的所属用户'' AND NAME=''刚才查到的过程名
mysql:
MyISAM的查看机制
table_locks_immediated和table_locks_waited.
InnoDB的
innodb_row_lock_current_waits
innodb_row_lock_time
innodb_row_lock_time_avg
innodb_row_lock_time_max
innodb_row_lock_waits