繁体   English   中英

MySQL 如何处理并发插入?

[英]How does MySQL handle concurrent inserts?

我知道 MySQL 中存在一个并发 SELECT 和 INSERT 的问题。 但是,我的问题是,如果我打开与 MySQL 的两个连接并继续使用它们加载数据,MySQL 是并发获取数据还是等待一个完成后再加载另一个?

我想知道 MySQL 在这两种情况下的行为。 就像我尝试在打开单独的连接时同时加载同一个表或不同表中的数据一样。

如果您将创建一个到数据库的新连接并从两个链接执行插入,那么从数据库的角度来看,它仍然是顺序的

MySQL 文档页面上的 并发插入文档说:

如果有多个 INSERT 语句,它们将与 SELECT 语句同时排队并按顺序执行。

请注意,无法控制两个并发插入的顺序。 这种并发中的顺序受许多不同因素的支配。 为了确保顺序,默认情况下您将不得不牺牲并发性。

MySQL 确实支持将数据并行插入到同一个表中。

但是并发读/写的方法取决于您使用的存储引擎。

数据库

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

我的ISAM

MySQL 对 MyISAM、MEMORY 和 MERGE 表使用表级锁定,一次只允许一个会话更新这些表,使它们更适合只读、多读或单用户应用程序

但是,上面提到的 MyISAM 表的行为可以通过concurrent_insert系统变量来改变,以实现并发写入。 详情请参阅此链接

因此,事实上,MySQL 确实支持 InnoDB 和 MyISAM 存储引擎的并发插入。

您询问死锁检测、ACID 和特别是 MVCC、锁定和事务:

死锁检测和回滚

InnoDB 自动检测事务死锁并回滚一个或多个事务以打破死锁。 InnoDB 尝试选择小事务进行回滚,其中事务的大小由插入、更新或删除的行数决定。 当 InnoDB 执行一个事务的完全回滚时,该事务设置的所有锁都会被释放。 但是,如果由于错误而仅回滚单个 SQL 语句,则可能会保留该语句设置的某些锁。 发生这种情况是因为 InnoDB 以一种格式存储行锁,以至于它之后无法知道哪个语句设置了哪个锁。

https://dev.mysql.com/doc/refman/5.6/en/innodb-deadlock-detection.html

锁定

保护事务免于查看或更改其他事务正在查询或更改的数据的系统。 锁定策略必须在数据库操作的可靠性和一致性(ACID 哲学的原则)与良好并发性所需的性能之间取得平衡。 微调锁定策略通常涉及选择隔离级别并确保所有数据库操作对于该隔离级别都是安全可靠的。

http://dev.mysql.com/doc/refman/5.5/en/glossary.html#glos_locking

代表原子性、一致性、隔离性和持久性的首字母缩写词。 这些属性在数据库系统中都是可取的,并且都与事务的概念密切相关。 InnoDB 的事务特性遵循 ACID 原则。 事务是可以提交或回滚的原子工作单元。 当一个事务对数据库进行多次更改时,要么在提交事务时所有更改都成功,要么在回滚事务时撤消所有更改。 数据库始终保持一致的状态——在每次提交或回滚之后,以及在事务进行时。 如果跨多个表更新相关数据,查询会看到所有旧值或所有新值,而不是旧值和新值的混合。 交易在进行中时相互保护(隔离); 他们不能相互干扰或看到彼此未提交的数据。 这种隔离是通过锁定机制实现的。 有经验的用户可以调整隔离级别,以减少保护以提高性能和并发性为代价,当他们可以确定事务确实不会相互干扰时。

http://dev.mysql.com/doc/refman/5.5/en/glossary.html#glos_acid

MVCC

InnoDB 是一个多版本并发控制 (MVCC) 存储引擎,这意味着单行的多个版本可以同时存在。 事实上,可能有大量这样的行版本。 根据您选择的隔离模式,InnoDB 可能必须让所有行版本回到最早的活动读取视图,但至少它必须让所有版本回到当前正在运行的 SELECT 查询的开头

https://www.percona.com/blog/2014/12/17/innodbs-multi-versioning-handling-can-be-achilles-heel/

这取决于。

这取决于客户端——有些客户端允许并发访问; 有些会序列化访问,从而失去预期的收益。 您甚至没有指定 PHP vs Java vs ... 或 Apache vs ... 或 Windows vs ... 许多组合根本不提供任何并行性。

如果不同的表,则只有 I/O、CPU、buffer_pool 上的互斥体等的一般争用。合理的并行度是可能的。

如果是同一个表,则取决于索引和访问模式。 在某些情况下,线程会相互阻塞。 在某些情况下,它甚至会“死锁”并回滚其中一项事务。 死锁不仅会减慢你的速度,还会让你重试插入。

如果您正在寻找大量行的高速摄取,请参阅我的博客 它列出了一些技术,并指出了一些后果,例如复制、引擎选择、多线程。

多个线程插入同一个表——这在很大程度上取决于您为任何PRIMARYUNIQUE键提供的值。 这取决于是否在同一事务中采取了其他操作。 这取决于涉及多少 I/O。 这取决于您是进行单行插入还是批处理。 这取决于......(抱歉含糊不清,但您的问题不是很具体。)

如果您想介绍两个或三个设计的细节,我们可以讨论这些细节。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM