暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[ACDU翻译] MySQL 8.11.1 内部锁方式

原创 由迪 2021-06-25
774

本节讨论内部锁定:即在MySQL服务器本身中进行锁定,以便通过多个会话来管理表内容的争夺。这种类型的锁定是内部的,因为它完全由服务器执行,不涉及其他程序。有关其他程序在 MySQL 文件上执行的锁定,请参阅第 8.11.5 节,“外部锁定”。

行级锁定

MySQL 使用行级锁定表来支持多个会话的同步写入访问,使其适合多用户、高度并发和 OLTP 应用程序。InnoDB

为了避免在单个表上执行多个并发写操作时陷入僵局,在交易开始时通过为预期要修改的每组行发布语句来获取必要的锁,即使数据更改语句在交易后期出现。如果交易修改或锁定多个表,则在每笔交易中以相同的顺序发布适用的对账单。死锁影响性能,而不是表示严重错误,因为默认情况下会自动检测死锁条件并回滚受影响的交易之一。InnoDB``SELECT ... FOR UPDATE``InnoDB

在高并发系统中,当许多线程等待相同的锁时,死锁检测可能会导致减速。有时,禁用死锁检测可能更有效,并在出现死锁时依靠innodb_lock_wait_timeout设置进行交易回滚。使用innodb_deadlock_detect配置选项可以禁用死锁检测。

行级锁定的优点:

  • 当不同的会话访问不同的行时,锁定冲突会更少。
  • 回滚更改更少。
  • 可以长时间锁定单行。

表级锁定

MySQL 使用桌面锁定(和表)来访问,每次只能更新一个会话。这种锁定级别使这些存储引擎更适合仅读取、主要读取或单用户应用程序。MyISAM``MEMORY``MERGE

这些存储引擎始终在查询开始时同时请求所有所需的锁,并始终以相同的顺序锁定表,从而避免僵局。权衡是,这种策略减少了并发性:想要修改表的其他会话必须等到当前数据更改语句完成。

表级锁定的优势:

  • 所需的内存相对较少(行锁定需要每行或锁定的行组内存)
  • 在表的很大一部分使用时速度很快,因为只涉及一个锁。
  • 如果您经常对大部分数据执行操作,或者必须经常扫描整个表,则速度会很快。GROUP BY

MySQL 授予表编写锁如下:

  1. 如果表上没有锁,就把写字锁放在上面。
  2. 否则,将锁定请求放入写入锁定队列中。

MySQL 授予表读取锁如下:

  1. 如果表上没有书写锁,请在上面放一个读取锁。
  2. 否则,将锁定请求放入读取锁定队列中。

表更新比表检索更优先。因此,当锁被释放时,锁会提供给写入锁队列中的请求,然后提供给读取锁队列中的请求。这确保了即使表具有繁重的选择活动,表的更新也不会"饿"到"。但是,如果表有许多更新,则选择语句将等待,直到没有更多更新。

有关更改读取和写入优先级的信息,请参阅第 8.11.2 节,“表锁定问题”。

您可以通过检查Table_locks_immediateTable_locks_waited状态变量来分析系统上的表锁争议,这些变量指示可以立即授予表锁请求的次数和必须等待的编号:

mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name         | Value   |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited    | 15324   |
+-----------------------+---------+

性能图马锁表还提供锁定信息。请参阅第 27.12.13 节,“性能图式锁表”。

存储引擎支持并发插入,以减少读者和编写者之间对给定表的争执:如果表在数据文件中间没有自由方块,则始终在数据文件的末尾插入行。在这种情况下,您可以自由地将"插入""选择"语句混合到没有锁的表中。即,您可以在其他客户端从表中阅读的同时将行插入表中。孔可能来自从表中间删除或更新的行。如果存在孔,则会禁用并发插件,但当所有孔都填充了新数据时,会再次自动启用。要控制此行为,请使用concurrent_insert系统变量。请参阅第 8.11.3 节,“并发插入”。MyISAM``MyISAM``MyISAM``MyISAM

如果您使用LOCK TABLE明确获取表锁,则可以请求锁定而不是锁,以便其他会话在锁定表时执行并发插入。READ LOCAL``READ

要在无法同时插入时在表上执行许多插入选择操作,您可以将行插入临时表,并使用临时表中的行更新真实表:t1``temp_t1

mysql> LOCK TABLES t1 WRITE, temp_t1 WRITE;
mysql> INSERT INTO t1 SELECT * FROM temp_t1;
mysql> DELETE FROM temp_t1;
mysql> UNLOCK TABLES;

选择锁定类型

通常,表锁在以下情况下优于行级锁:

  • 表的大多数语句都是读取的。

  • 表的语句是读取和写入的混合体,其中写入是单行的更新或删除,可以用一个键读取:

    UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;
    DELETE FROM tbl_name WHERE unique_key_col=key_value;
    
  • 选择与并发的插入语句相结合,很少更新删除语句。

  • 许多扫描或操作在整个表上没有任何编写器。GROUP BY

使用更高级别的锁,您可以通过支持不同类型的锁来更轻松地调整应用程序,因为开销上的锁比行级锁要少。

行级锁定以外的选项:

  • 版本(例如MySQL中用于并发插入的版本),其中可以同时拥有一个编写器和许多读者。这意味着数据库或表根据访问开始的时间支持数据的不同视图。其他常见的术语是"时间旅行"、“按需复制"或"按需复制”。
  • 按需复制在许多情况下优于行级锁定。然而,在最坏的情况下,它可以使用更多的内存比使用正常的锁。
  • 您可以使用应用级别的锁,例如 MySQL 中的GET_LOCK()RELEASE_LOCK()提供的应用级别锁,而不是使用行级锁。这些是咨询锁,因此它们仅适用于相互合作的应用程序。请参阅第 12.15 节,“锁定功能”。
最后修改时间:2021-06-26 15:52:35
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论