Mysql 事务数据库和防止死锁

Mysql 事务数据库和防止死锁,mysql,database,innodb,rsync,database-deadlocks,Mysql,Database,Innodb,Rsync,Database Deadlocks,我正在开发云服务,将本地数据库(订单接收POS系统)同步到中央远程数据库。我们的远程数据库正在为每个表运行最新版本的mysql 5.6和innoDB表引擎。基本上,它是一个事务性数据库,经历了大量的事务,主要是写入(即插入和更新),有时在查看报告时还经历了读取等。我们不可避免地遇到了第一次数据库死锁(请注意,这发生在升级mysql 5.6之前),我对死锁原因的理解可能是,有两个连接试图同时读取或写入一行。我也知道死锁很常见,需要正确的代码来尝试/捕获我认为我已经成功实现的死锁。 为了缓解死锁,我

我正在开发云服务,将本地数据库(订单接收POS系统)同步到中央远程数据库。我们的远程数据库正在为每个表运行最新版本的mysql 5.6和innoDB表引擎。基本上,它是一个事务性数据库,经历了大量的事务,主要是写入(即插入和更新),有时在查看报告时还经历了读取等。我们不可避免地遇到了第一次数据库死锁(请注意,这发生在升级mysql 5.6之前),我对死锁原因的理解可能是,有两个连接试图同时读取或写入一行。我也知道死锁很常见,需要正确的代码来尝试/捕获我认为我已经成功实现的死锁。 为了缓解死锁,我考虑设置两个相互镜像的数据库 A) 写入的数据库 b) 已读取的数据库

基本上,从本地到远程的同步将写入数据库A,在后台使用rsync将数据库A镜像到B,哪个数据库B将用于读取和查询报告,因为rsync不使用数据库连接来读取用于同步的数据

我的问题是,这种结构在缓解死锁方面是否有效,并且在服务器上是否存在任何重大性能问题

我希望我的问题对我想要实现的目标有意义


提前感谢。

数据库复制有助于提高性能和可用性。但是,在开始复制数据库之前,您可能需要检查许多方面

我假设您已打开旋钮来记录慢速查询。我建议您进行分析,看看是否有机会优化导致问题的查询。 另一件事是,尽管重新建模数据并不总是那么容易,但它有时会有所帮助。 验证您的报告查询是否根据需要使用索引。 您还可以研究数据分区


有时,根据您的数据量和报告要求,您可以考虑使用NoSQL数据库进行分析数据。

死锁不是两个连接试图同时写入同一行的结果。只是比那复杂一点

会产生死锁的场景如下所示:

有两个资源(可能是一个表中的两行、两个表、两个文件等,我们将其标识为“a”和“B”)

  • 连接#1锁定资源“A”
  • 连接#2锁定资源“B”
  • 连接#1继续尝试锁定“B”(同时仍保持对“A”的锁定)。由于连接#2已锁定“B”,因此连接#1等待解除锁定
  • 连接#2(仍保持对“B”的锁定)尝试锁定“A”。由于连接#1已锁定“A”,因此连接#2等待释放该锁
  • 两个连接现在都处于一种状态,每个连接都在等待另一个释放其锁;他们陷入僵局。死锁只能通过一个连接中止其释放锁的操作,从而允许另一个连接完成来打破


    在数据库中,从行到页再到表,这种事情可以在任何粒度级别发生,也可以在数据或索引中发生。让数据库引擎自行执行乐观锁定通常可以提供最佳性能,但可能会导致死锁。您可能需要在可序列化的事务中执行一些插入/更新(尽管这会导致性能下降)。考虑在一个死锁场景中触摸多个表作为潜在参与者的事务。

    < P>放弃完全消除死锁。专注于“减轻”它们

    只要可行,按某种规范的顺序触摸表和行。一个简单的例子是在子句中对
    中的元素进行排序。我认为以下情况可能导致僵局:

    UPDATE ... WHERE id IN (3,7) -- in one connection
    UPDATE ... WHERE id IN (7,3) -- in another connection
    
    但是,如果对所有事务中的ID进行排序,最糟糕的情况是一个连接会等待另一个连接释放行锁。(这就是
    innodb\u lock\u wait\u timeout
    发挥作用的地方。)

    另一个例子涉及

    BEGIN;
    SELECT ... FROM table1  FOR UPDATE;
    SELECT ... FROM table2  FOR UPDATE;
    ...
    COMMIT;
    
    当然,在某些情况下,您无法预测事务中需要哪些ID或表,因此无法进行简单的排序。这就是为什么你必须准备好抓住僵局


    当您遇到死锁时,只需重播事务即可。好的,如果事务中有其他代码,这可能并不简单。

    我相信我已经正确地索引了,但是我的表没有使用自动递增,而是使用外键组合作为主索引。例如orderid,clientid。是否所有表都应该使用in id自动递增?顺便说一句,我正在记录慢速查询并优化我的查询。另一方面,我在表中添加了另外两个索引以优化查询时间,不确定多个索引是否也有助于导致死锁,感谢您更好地向我解释死锁。*考虑在一个死锁场景中触摸多个表作为潜在参与者的事务。您是指插入多个表还是使用SelectPrimary时,并发插入和/或更新将是死锁场景中的罪魁祸首。并发选择永远不会成为问题。带有插入/更新的选择也不应该,但我不会说“从不”;根据使用的事务模式,可能会在仅执行选择的事务和执行插入或更新的事务之间引发死锁。