高性能MySQL04-锁机制

一、简介

MySQL中有着Lock和Latch的概念,在数据库中,这两者都可以被称为“锁”,但是两者有着截然不同的含义。

Latch一般称为闩锁(轻量级的锁),因为其要求锁定的时间必须非常短。若持续的时间长,则应用的性能会非常差,在InnoDB引擎中,Latch又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制。

Lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放(不同事务隔离级别释放的时间可能不同)。

二、锁的类型

对数据的操作其实只有两种,也就是读和写,而数据库在实现锁时,也会对这两种操作使用不同的锁。

这两种类型的锁通常被称为共享锁(shared lock)和排它锁(exclusive lock),也叫读锁(read lock)和写锁(write lock)。

读锁是共享的,或者说是相互不阻塞的。多个客户在同一时刻可以同时读取同一个资源,而互不干扰。

写锁则是排它的,也就是说一个写锁会阻塞其它的写锁和读锁,这样可以只允许一个人进行写入,防止其他用户读取正在写入的资源。

三、锁粒度

Lock锁根据粒度主要分为表锁、页锁和行锁。不同的存储引擎拥有的锁粒度都不同。每种MySQL存储引擎都可以实现自己的锁策略和锁粒度。

1、表锁(table lock)

表级别的锁定是MySQL各存储引擎中最大颗粒度的锁定机制,并且是开销最小的策略。表锁会锁定整张表。一人用户对表进行写入(插入、删除、更新等)前,需要先获得写锁,这会阻塞其它用户对该表的所有读写操作。只有没有写锁时,其它读取的用户都能获得读锁,读锁之间是相互不阻塞的。

尽管存储引擎可以管理自己的锁,MySQL本身还是会使用各种有效的表锁来实现不同的目的。例如,服务器会为诸如ALTER TABLE之类的语句使用表锁,而忽略存储引擎的锁机制。

使用表级锁定的主要是MyISAM,MEMORY,CSV等一些非事务性存储引擎。

2、行锁(row lock)

行级锁定最大的特点就是锁定对象的粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。

虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,所以也带来了最大的锁开销。此外,行级锁定也最容易发生死锁。

使用行级锁定的主要是InnoDB存储引擎。

四、死锁

死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。当多个事务试图以不同的顺序锁定资源时,就可能会产生死锁多个事务同时锁定同一个资源时,也会产生死锁。

如下:

事务1:
START TRANSACTION;
UPDATE test SET age = 45 WHERE id = 4;
UPDATE test SET age = 19 WHERE id = 3;
COMMIT;

事务2:
START TRANSACTION;
UPDATE test SET age = 20 WHERE id = 3;
UPDATE test SET age = 47 WHERE id = 4;
COMMIT;

如果凑巧,两个事务都执行了第一条UPDATE语句,更新了一行数据,同时也锁定了该行数据,接着每个事务都尝试去执行第二条UPDATE语句,却发现已经被对方锁定,然后两个事务都在等待对方释放锁,同时又持有对方需要的锁,则陷入死循环。除非有外部因素介入才可能解除死锁。

InnoDB目前处理死锁的方法是,将持有最少等级排它锁的事务进行回滚(这是相对比较简单的死锁回滚算法)。

死锁发生以后,只有部分或者完全回滚其中一个事务,都能打破死锁,对于事务型的系统,这是无法避免的。

五、总结

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。

参考

1、《高性能MySQL》 [美]Baron Scbwartz, Peter Zaitsev, Vadim Tkacbenko 著
2、 蹲厕所的熊谈谈MySQL的锁

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章