Mysql SQL-有更好的方法处理一个表上的多个事务吗?

Mysql SQL-有更好的方法处理一个表上的多个事务吗?,mysql,sql-server,database,Mysql,Sql Server,Database,假设您在某个关系数据库中有一个SQL表(SQL Server、MySQL等等)。假设您有500个每15分钟运行一次的任务。每个任务将删除与该任务相关的一部分数据,插入与该任务相关的新数据,然后外部源将选择与该任务相关的数据 根据我的经验,这不可避免地会导致死锁、超时,甚至在进行脏读时,selects的性能都低于标准 你可以尽量错开任务的开始时间,但这并不能真正解决问题。任务太多,总是会有重叠 您可以尝试使用更好的CPU升级服务器以处理连接,但这对于500个任务来说是非常昂贵的 因此,我所做的是复

假设您在某个关系数据库中有一个SQL表(SQL Server、MySQL等等)。假设您有500个每15分钟运行一次的任务。每个任务将删除与该任务相关的一部分数据,插入与该任务相关的新数据,然后外部源将选择与该任务相关的数据

根据我的经验,这不可避免地会导致死锁、超时,甚至在进行脏读时,selects的性能都低于标准

你可以尽量错开任务的开始时间,但这并不能真正解决问题。任务太多,总是会有重叠

您可以尝试使用更好的CPU升级服务器以处理连接,但这对于500个任务来说是非常昂贵的

因此,我所做的是复制表模式,并为每个任务提供它自己的具有该模式的不同表。 此外,在为表构造新数据时,它所做的只是将数据插入到一个新表中,然后用该表翻转当前表的名称

创建表格任务001_表格_非活动

将新数据大容量插入Task001\u表\u

删除表格任务001_表格_活动

重命名Task001\u表\u非活动Task001\u表\u活动

优点:

-快速处理。SQL从来都不擅长不断删除。大容量插入和翻转名称的功能大大缩短了任务的处理时间

-可伸缩。现在,所有这些插入和删除都不是为了一个表而不断地争吵,我可以在云中一台非常便宜的机器上运行许多任务

-反碎片化。由于每次都会重新创建该表,因此任何困扰系统的不断删除的碎片问题都不再是问题

-选择尽可能快,无需脏读。由于插入是在单独的表中完成的,因此外部源执行的select语句将尽可能快,而无需执行脏读。这是我最大的优势

-快速迁移。最终,我会有太多的任务,并用尽处理能力,即使有这种设置。因此,如果我需要将一个任务迁移到另一台服务器,只需复制两个表,而不是在一个blob表上复制一个粗糙且速度极慢的select语句

-可转位性。当一个表变得太大(300行+)时,您不能为它编制索引。不管怎样,它都会因为事务缓冲区的限制而中断几天。SQL就是这样。通过将巨大的blob表分割成更小的表,您可以成功地编制索引。结合并行化,您可以比在一个大表上进行索引更快地索引所有数据

缺点:

-使GUI中的表导航变得困难

-使select/schema alter语句有点棘手,因为现在它必须在每个表上执行某种类型的游标操作,如%table%,并对每个表应用SQL命令


那么,如果模式复制有这么多优点,为什么许多SQL爱好者都讨厌它呢?是否有更好的方法处理此问题?

没有足够的信息提供建议,但应考虑以下内容:

  • 快照隔离 除非恢复数据库,否则快照事务在读取数据时不会请求锁定。读取数据的快照事务不会阻止其他事务写入数据。写入数据的事务不会阻止快照事务读取数据
  • 使用事务性复制/日志传送/镜像/更改数据捕获等来卸载主表
  • 不是删除,而是软删除(更新IsDeleted标志或维护xxxx_删除表)是一个选项

如果系统(数据库、硬件、网络体系结构)设计正确,即使每秒有数千个DML请求,也不会出现任何问题。

在Microsoft SQL Server中,如果任务从未触及不属于它们的行,则可以尝试使用乐观或悲观版本控制-


根据您的情况,读取提交的快照隔离(RCSI)或快照隔离级别都可以做到这一点。如果两者都适合您,我会推荐前者,因为它会大大降低性能开销。

有趣。读了之后,读提交的快照隔离似乎就更新和选择而言肯定会起到作用。但是移民呢?最终,我将不得不将一些任务卸载到新服务器上。我怎么知道也要移植哪些临时表?看起来真的很乱。软删除是一个非常有趣的想法,但您必须在某个时候清除数据。在表中保留太多的虚拟数据只会最终降低查询速度,对吗?重新软删除:是的,如果您预期删除的数据量很大,您可以安排一项维护任务,在安静的时间(例如周末晚上)物理删除循环(前10K)中的记录。明白了,这是有意义的。我喜欢这个答案。好消息。谢谢AntonI,我的系统上也有类似的负载。读取提交的快照隔离为我的死锁创造了奇迹。