MySQL如何处理并发插入?

时间:2015-08-19 05:32:46

标签: mysql

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

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

4 个答案:

答案 0 :(得分:30)

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

MySQL文档页面上的Concurrent Inserts文档说:

  

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

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

答案 1 :(得分:9)

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

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

InnoDB的

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

的MyISAM

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

但是,MyISAM表的上述行为可以通过concurrent_insert系统变量进行更改,以实现并发写入。请参阅to this link了解详情。

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

答案 2 :(得分:7)

您询问死锁检测,ACID和特殊MVCC,锁定和交易:

死锁检测和回滚

  

InnoDB自动检测事务死锁并回滚a   交易或交易打破僵局。 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

<强> ACID

  

首字母缩略词代表原子性,一致性,隔离性和   耐久性。这些属性在数据库系统中都是可取的,   并且都与交易的概念密切相关。该   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/

答案 3 :(得分:3)

取决于。

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

如果是不同的表,则只能对buffer_pool上的I / O,CPU,互斥锁等进行一般争用。可以实现合理的并行度。

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

如果您希望高速摄取大量行,请参阅my blog。它列出了技术,并指出了各种后果,例如复制,引擎选择,多线程。

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

如果您想提供有关两个或三个设计的细节,我们可以讨论具体细节。