核心知识点:
1.表锁和行级锁代表着锁的级别;读锁和写锁代表锁定真实类型。
2.读锁属于共享锁,共享同一资源,互不干扰;写锁属于排他锁,为了安全起见,写锁会阻塞其他的读锁和写锁。
3.表锁的开销最小,行级锁的开销最大。
4.使用表锁不用考虑存储引擎,行级锁是由存储引擎实现的,而不是由MySQL服务器来实现。
5.每种锁都有特定的用途,看似没用的表锁与ALTER TABLE就很搭调。
无论何时,只要不止一个查询同时修改数据,都会产生并发控制问题。而解决并发问题最直接的方法就是上锁,以此来限制事务的开始。
这样,创建何种类型的锁才能让系统资源的利用率更高,执行的速率更快,就是主要问题。
当然本章也不会阐述如何建锁,这属于优化层面的问题。下面会阐述几个关于概念性的问题,包括读锁、写锁、表锁等。
1.读锁/写锁
在处理并发或并写时,系统会使用一套锁系统来解决问题。这种锁由两类锁组成,通常称之为共享锁和排他锁,或者叫读锁和写锁。
关于锁的概念:某一资源上的读锁是共享的,或者说是互不阻塞的。在同一时间,多个用户可以读取同一资源,而互不干扰。
另一方面,写锁是排他的,也就是说,一个写锁会阻塞其他的读锁和写锁,这是出于安全的考虑,
在给定的时间里,只有一个用户能写入资源,以防止用户在写操作的同时其他用户读取同一资源。
对于数据库来说,随时随地都会发生锁。当某一用户修改某一部分数据时,MySQL会禁止其他用户读取统一数据。
大多数时候,MySQL都是以透明的方式实现锁的内部管理。
2.锁粒度
一种提高共享资源并发性的方法就是让锁定对象更有选择性。要记住只锁定部分须修改的数据,而不是所有的资源。
更理想的方式是,只对要修改的数据片精确加锁。任何时间,在给定的资源上,被加锁的数据量越小,就可以允许更多的并发修改,只要互相之间互不冲突即可。
这么做的问题是加锁也会消耗系统资源。每一种锁操作、检查锁是否已解除以及释放锁等,都会增加系统的开销。
如果系统花费大量的时间来管理锁,而不是读/写数据,那么系统整体性可能会因此受到影响。
所谓的锁策略,就是在锁开销和数据安全之间寻求一种平衡,这种平衡也能影响系统性能,
大多数的商业数据库服务器没有提供更多的选择,通常都是在表上施加行级锁,并提供复杂的手段,在有锁的情况下改善系统的性能。
而另一方面,MySQL则提供了多种选择。每种MySQL存储引擎都可以实现独有的锁策略或锁颗粒。
在存储引擎设计中,锁管理是个非常重要的议题。
将颗粒度调整到某一水平,也许能为某种应用目的提供更佳的性能,不过,这也可能使存储引擎又不适用于其他的用途了。
由于MySQL可以提供多种存储引擎,所以它不需要一个通用解决方案。下面介绍两种最重要的锁策略。
表锁(Table lock)
MySQL支持大多数基本的锁策略,其中开销最小的锁策略是表锁。
表锁将整张表加锁。当一个用户对表进行写操作(如插入、删除、更新)时,用户可以获得一个写锁。
写锁会禁止其他用户的读/写操作。另外,只有无人做写操作时,用户才能获得读锁,读锁之间是互不冲突的。
在特定的环境中,表锁可能性能良好。例如,READ LOCAL表锁支持某种类型的并发写操作。
另外,写锁比读锁有更改的优先级,即使有读操作用户已排在队列中,,一个被申请的写锁仍可以排在锁队列的前列(写锁会被安置在读锁之前,而读锁不能排在写锁之前)。
虽然存储引擎管理自己的锁,MySQL本身也能使用各种有效的表锁,以用于各种目的。
例如,MySQL服务器可以在语句中,如ALTER TABLE语句中,使用表锁,而不用考虑存储引擎,同时花销也小。
行级锁(Row locks)
行级锁可以支持最大的并发处理(同时也带来最大的锁开销)。众所周知,行级锁在InnoDB和Falcon存储引擎中得以实现,在其他一些存储引擎中也有实现。
行级锁由存储引擎实现,而不是MySQL服务器实现。所有存储引擎都是以自有方式实现加锁机制的。