本节讨论内部锁;也就是说,在MySQL服务器本身内部执行锁定,以管理多个会话对表内容的争用。这种类型的锁定是内部的,因为它完全由服务器执行,不涉及其他程序。其他程序对MySQL文件执行的锁定,请参见第8.11.5节,“外部锁定”.
MySQL使用行级锁为InnoDB
表支持多个会话同时写访问,使其适合于多用户、高并发和OLTP应用程序。
为了避免死锁当对单个文件执行多个并发写操作时InnoDB
表,在事务开始时通过发出选择……更新
语句,即使数据更改语句稍后出现在事务中,也要对期望修改的每一组行进行修改。如果事务修改或锁定多个表,则在每个事务中以相同的顺序发出适用的语句。死锁会影响性能,而不是表示严重的错误,因为InnoDB
自动检测出现死锁并回滚一个受影响的事务。
在高并发性系统中,当多个线程等待同一个锁时,死锁检测可能会导致减速。有时,禁用死锁检测并依赖于innodb_lock_wait_timeout
设置为发生死锁时的事务回滚。可以使用。禁用死锁检测innodb_deadlock_detect
配置选项。
行级锁定的优点:
当不同的会话访问不同的行时,锁冲突更少。
回滚的更改更少。
可以长时间锁定一行。
MySQL使用表级锁为MyISAM
,内存
,合并
表,每次只允许一个会话更新这些表。这种锁定级别使这些存储引擎更适合只读、多读或单用户应用程序。
这些存储引擎避免死锁通过总是在查询开始时一次请求所有需要的锁,并且总是以相同的顺序锁定表。这种策略的代价是降低了并发性;其他想要修改表的会话必须等待,直到当前数据更改语句完成。
表级锁的优点:
所需的内存相对较少(行锁定需要锁住每一行或每组行的内存)
当在表的大部分上使用时速度很快,因为只涉及单个锁。
如果你经常这样做,那就快一点
集团
对大部分数据的操作或必须频繁地扫描整个表。
MySQL授予表写锁如下:
如果表上没有锁,就给它加一个写锁。
否则,将锁请求放在写锁队列中。
MySQL授予表读锁如下:
如果表上没有写锁,就给它加一个读锁。
否则,将锁请求放入读锁队列中。
表更新比表检索具有更高的优先级。因此,当锁被释放时,写锁队列中的请求可以使用该锁,然后读锁队列中的请求可以使用该锁。这可以确保对表的更新不会发生”饿死了”即使有沉重的选择
活动。但是,如果一个表有很多更新,选择
语句会一直等待,直到没有更新。
有关更改读写优先级的信息,请参见第8.11.2节,“表锁定问题”.
可以通过检查。来分析系统上的表锁争用Table_locks_immediate
而且Table_locks_waited
状态变量,分别表示可以立即授予表锁请求的次数和需要等待的次数:
mysql> SHOW STATUS LIKE 'Table%'+-----------------------+---------+ | Variable_name |值 | +-----------------------+---------+ | Table_locks_immediate | 1151552 | | Table_locks_waited | 15324年 | +-----------------------+---------+
Performance Schema锁表还提供锁信息。看到第25.12.12节,“性能模式锁表”.
的MyISAM
存储引擎支持并发插入,以减少给定表的读写者之间的争用MyISAM
表在数据文件的中间没有空闲块,行总是插入到数据文件的末尾。在这种情况下,您可以自由地混合并发插入
而且选择
语句的MyISAM
表没有锁。也就是说,您可以将行插入到MyISAM
在其他客户端读取它的同时。从表中删除或在表中间更新的行可能会导致hole。如果有孔,则禁用并发插入,但在所有孔被新数据填充后,会自动再次启用。要控制此行为,请使用concurrent_insert
系统变量。看到第8.11.3节,“并发插入”.
如果您显式地使用锁表
,可以请求一个阅读当地
锁而不是读
锁定,使其他会话能够在您锁定表时执行并发插入。
执行许多插入
而且选择
表上的操作t1
当无法进行并发插入时,可以将行插入到临时表中temp_t1
并使用临时表中的行更新真实表:
mysql> LOCK TABLES t1 WRITE, temp_t1 WRITE;INSERT INTO t1 FROM temp_t1删除temp_t1中的>mysql >解锁表;
通常,表锁在以下情况下优于行级锁:
使用高级锁,您可以通过支持不同类型的锁更容易地调优应用程序,因为锁开销比行级锁要小。
行级锁定以外的选项:
版本控制(比如MySQL中用于并发插入的版本控制),可以同时有一个写入器和多个读取器。这意味着数据库或表根据访问开始的时间支持不同的数据视图。其他常见的术语是”时间旅行,””文案写,”或”按需复制。”
按需复制在许多情况下优于行级锁定。但是,在最坏的情况下,它会比使用普通锁占用更多的内存。
与使用行级锁不同,您可以使用应用程序级锁,例如由
GET_LOCK ()
而且RELEASE_LOCK ()
在MySQL。这些是建议锁,因此它们只适用于相互协作的应用程序。看到第12.15节,“锁定函数”.