MySQL锁简单了解

来源:互联网 发布:德国人身高体重的数据 编辑:程序博客网 时间:2024/06/11 05:38
在MySQL中有三种锁定机制:表级锁定、行级锁定和页级锁定


表级锁定

其中MyISAM使用的就是表级锁定,下面说说表级锁定的特点

表级锁定的类型包括:读锁定、写锁定

当线程A对表A进行读锁定后:

线程A可以对表A进行读操作、线程A对其进行update操作时会报错,提示表被读锁定

线程B可以对表A进行读操作、线程B对其进行update操作时会被阻塞,直到线程A释放了对表A的读锁定,

当线程A对表A进行读锁定加上local选项:

线程B可以对表A进行Insert操作,线程B对表A进行Update操作会被阻塞,直到线程A释放了对表A的读锁定

当线程A对表A进行写锁定后:

线程A可以对表A进行读操作

线程B对表A的读操作将会被阻塞,直到线程A释放了对表A的写锁定


行级锁定

行级锁定并不是由MySQL提供的锁定机制,而是由存储引擎自己实现的,其中Innodb的锁定机制就是行级锁定。

行级锁定的类型包括:共享锁、排它锁、意向共享锁、意向排它锁。

当一个事务需要给自己需要的某个资源加锁的时候,如果遇到一个共享锁正锁定着自己需要的资源的时候,自己可以再加一个共享锁,但是不能加排它锁;如果自己需要锁定的资源已经被一个排它锁锁定之后,就只能等待该锁定释放资源以后自己才能获得锁定资源并添加自己的锁定。如果自己需要锁定的资源被一个排它锁锁定,那么自己可以在这个资源上加一个合适的意向锁,如果自己是想要一个共享锁,那么可以在该资源上加一个意向共享锁,如果自己想要一个排它锁时,可以在该资源上加一个意向排它锁,前提是该资源上没有其他的意向排它锁。也就是共享锁和意向共享锁可以允许有多个,但是排它锁和意向排它锁只允许有一个。

Innodb的行级锁是通过在指向数据记录的第一个索引键之后和最后一个索引键之后的空域空间上标记锁定信息,这种锁定方式被称为“间隙锁”。这种锁定机制是通过索引来实现的,也就是说如果无法利用索引的时候,Innodb就会放弃使用行级锁定而改用表级锁定

死锁的产生,在行级锁中会出现死锁的情况,当两个线程互相等待对方的资源释放之后才能释放自己的资源,这样就造成了死锁。

在Innodb的事务管理和锁定机制中,有专门用于检测死锁的机制,当检测到死锁时,Innodb会选择产生死锁的两个事务中较小的一个产生回滚,而让另外一个较大的事务成功完成,那么如果判断事务的大小呢,在手册中的介绍是通过计算两个事务各自插入、更新或者删除的数据量来判断的,也就是说哪个事务改变的记录数越多,在死锁中越不会被回滚,需要的主意的是,如果在产生死锁的场景中涉及到不止Innodb存储引擎时,Innodb是检测不到该死锁的,这时就只能通过锁定超时限制来解决该死锁了。




数据库锁定机制是数据库为了保证数据的一致性而使各种共享资源在并发访问时访问变得有序所设计的一种规则。


MySQL各存储引擎使用了3种类型的锁定机制:


1. 行级锁定(row-level) --- MyISAM、Memory、CSV

*锁定对象颗粒度最小,发生资源争用的概率最小,在并发处理能力上有较大优势。

*缺点是每次获取锁和释放锁需要做的事情很多,带来消耗大,也最容易发生死锁。


2. 表级锁定(table-level)--- Innodb、NDB Cluster

*锁定对象颗粒度最大,实现逻辑简单,获取锁和释放锁的速度很快,一次会将整个表锁定,可以很好避免死锁。

*缺点是出现资源争用的概率最高,致使并发度大打折扣。

*主要分为2种类型:读锁定和写锁定

*通过4个锁定队列来维护这2种锁定:

Current read-lock queue (lock->read) --- 存放持有读锁的所有线程,按获取到锁的时间顺序存放

Pending read-lock queue (lock->read_wait) --- 存放正在等待锁定资源的线程

Current write-lock queue (lock->write) --- 存放持有写锁的所有线程,按获取到锁的时间顺序存放

Pending write-lock queue (lock->write_wait) --- 存放正在等待锁定资源的线程

*MySQL内部实现表锁定多达11种类型,由系统中的一个枚举量(thr_lock_type)定义,各值描述如下:

IGNORE --- 当发生锁请求的时候内部交互使用,在锁定结构和队列中并不会有任何信息存储

UNLOCK --- 释放锁定请求的交互用锁类型

READ --- 普通读锁定

WRITE --- 普通写锁定

READ_WITH_SHARED_LOCKS --- 在Innodb中使用到,由如下方式产生:SELECT ... LOCK IN SHARE MODE

READ_HIGH_PRIORITY --- 高优先级读锁定

READ_NO_INSERT --- 不允许Concurrent Insert的锁定

WRITE_ALLOW_WRITE --- 当由存储引擎自行处理锁定的时候,mysqld允许其他的线程再获取读或写锁定,因为即使资源冲突,存储引擎自己也会知道怎么处理

WRITE_ALLOW_READ --- 这种锁定发生在对表做DDL(ALTER TABLE ...)的时候,MySQL可以允许其他线程获取读锁定,因为MySQL是通过重建整个表然后再RENAME而实现的该功能,所以整个过程原表仍然可以提供读服务

WRITE_CONCURRENT_INSERT --- 正在进行Concurrent Insert 时候所使用的锁定方式,该锁定进行的时候,除了READ_NO_INSERT之外的其他任何读锁定请求都不会被阻塞

WRITE_DELAYED --- 在使用INSERT DELAYED时候的锁定类型

WRITE_LOW_PRIORITY --- 显示声明的低级别锁定方式,通过设置LOW_PRIORITY_UPDAT = 1 而产生

WRITE_ONLY --- 当在操作过程中某个锁定异常中断之后系统内部需要进行CLOSE TABLE操作,在这个过程中出现的锁定类型就是WRITE_ONLY



3. 页级锁定(page-level) --- BerkeleyDB

锁定颗粒度介于行级锁定和表级锁定之间,所需资源开销以及所能提供的并发能力也介于两者之间,与行级锁定一样会发生死锁。

0 0
原创粉丝点击