调度和锁定
在很多客户一起查询数据表时,如果使客户能最快地查询到数据就是调度和锁定做的工作了。在mysql中,我们把select操作叫做读,把对数据表修改增加的操作(insert,update,replace...)叫做写。mysql的基本调度策略可以归纳为以下两条:
写入请求将按它们到达服务器的顺序进行处理;
写操作的优先级要高于读操作。
myisam和isam数据表的调度策略是在数据表锁的帮助下实现的,在客户程序要访问数据表之前,需获得相应的锁,在完成对数据表的操作后,再释放该锁。锁的管理通常由服务器管理,也可人为地用lock tables和unlock tables命令来申请和释放锁。写操作时,需要申请一个独占性的锁,也就是说在写操作其间,该表只能由写操作的客户使用。读操作时,客户必须申请一个允许其他客户对数据表进行写操作的锁,以确保客户在读的过程中数据表不会发生改变。但读操作锁不是独占的,可有多个读操作同时作用于同一个数据表。
通过一些修饰符可影响调度策略,如low_priority(用于delete,insert,load data,replace,update语句)、high_priority(用于select语句)、delayed(用于insert和replace语句)。它们的作用是这样的:
low_priority会使写操作的优先级降低到读操作以下,也就是说读操作会阻塞该级别的写操作,select的high_priority有类似的作用。
insert语句中的delayed修饰会使插入操作被放入一个“延迟插入”队列。并返回状态信息给客户,使客户程序可在新数据行还没插入到数据表之前继续执行后面的操作。如果一直有客户读该数据表,新数据行会一直待在队列中,直到数据表没有读操作时,服务器才会把队列中的数据行真正插入到数据表中。该语句可用在以下场合,在一个有冗长查询的数据表中插入数据,而你又不想被阻塞,你就可发出insert delayed语句,把插入操作放入服务器“延迟插入”队列,你无需等待就马上可进行接下来的操作。
当一个数据表里从未进行过删除操作或刚刚对它进行过碎片整理的情况下,用insert语句插入的数据行只会被添加到数据表的末尾,而不会插入到数据表的中间位置。这样,对于myisam表,mysql允许在有其它客户正在读操作的时间进行写操作。我们称之这并发插入。要使用该技巧,需注意以下两个问题:
不要在insert语句中使用low_priority修饰符。
读操作应用lock tables ... read local而不是用lock tables ... read语句来进行数据表读锁定。local关键字只对数据表中已存在行进行锁定,不会阻塞把新行添加到数据表末尾。
bdb数据表使用页面级操作锁,innodb数据表使用数据行级操作锁。所以这两种表的并发性比myisam和isam数据表这种表级锁的并发性会好很多。其中innodb的并发性最好。综上所述,我们可得出以下结论:
myisam和isam数据表的检索速度最快,但如果在检索和修改操作较多的场合,会出锁竞争的问题,造成等待时间延长。
bdb和innodb数据表能在有大量修改操作的环境下提供很好的并发性,从而提供更好的性能。
myisam和isam数据表由于进行表级锁定,所以不会出现死锁现象,bdb和innodb数据表则存在死锁的可能性。