当前位置:C++技术网 > 资讯 > mysql执行update更新未更改的数据的问题探讨

mysql执行update更新未更改的数据的问题探讨

更新时间:2017-11-24 08:55:46浏览次数:1+次

    在数据库中更新数据是非常常见的SQL应用场景,比如更新一个状态。在实时接收到设备的状态时,我们会将设备的状态更新到数据库中,以便浏览器端可以浏览到最新的设备状态。设备定时上报状态,程序也就定时更新设备的状态。
    按照通常的思路,我们就把设备的状态不断的更新到数据库的对应的数据表的状态字段。定时上报的状态,当然可以是一样的。比如设备空闲,在一个小时内可能都是空闲的,所以在上报状态时状态是空闲的。所以在多次更新设备状态的时候,我们都会直接将状态更新到数据表里就可以了。
    我们的想法是,不管数据表存储的状态是不是当前状态,更新进去都没有问题。如果不一样,就更改了状态。如果一样,更新的还是原来的数值而已。在程序实现上,也简单直接。
    但是在我实际测试的时候,却发现了一个奇怪的现象。在更新状态时,经常出现更新失败的情况。经过一番的检查,最后直接手动测试。发现只要是要更新的状态与数据库存储的状态相同,更新就会失败,而如果状态不同,则成功。
    失败和成功的定义是这样的:检测是否成功的标准就是数据表操作时影响的行数。也就是说,如果操作了一条数据,应该会返回影响一行的数据。这样我们就可以判定为执行成功。如果操作被影响的行数与被操作的行数不一样,则表示失败。在更新一个状态的时候,自然也就一次只会影响一行。
    然而当我准备更新的数据和数据库中的数据是一致的,mysql的更新返回的影响行数是0。这样,程序在检测的时候,就以为更新没有成功,所以提示更新状态失败。
    mysql之所以这么做,应该是为了提高效率,但是这样的策略,我们程序也就检测不能简单粗暴了。既然知道问题所在,我们就好处理了。
    需要了解的是,在SQL SERVER中,即使要更新的数据与数据表中的数据一样,SQL SERVER也会执行更新操作,然后返回被影响的行数为应该的行数。只是mysql没有真正的执行这个动作,直接返回了。在mysql看来,这样的操作是没有意义的,因为数据不会更改,操作一次降低了性能。但是没有考虑到程序在检测性的需要。其实mysql完全可以不执行这个动作,但是返回被影响的行数,让别人知道,mysql是知道执行了之后和执行之前一样,那么这次执行动作我们就可以理解为是执行成功。而返回的行数也可以给程序做一个成功的判断条件。
    mysql如何知道要更新的数据和存储的数据是一样的呢?自然是查询咯。查询当然会比更新操作要更快,自然会提高效率。我们为了让我们程序检测的更加准确,那么我们就需要先对状态进行检查,如果和要更新的数据是一样的,那么我们直接返回更新成功。这样也就是用查询代替了更新操作。然而如果确实有数据更新,那么就会损失一次查询的性能。如果我们必须确保状态更新能够准确检测,这样的检测就必须要有。当然,如果你有更高明的检测方法,那就可以避开这个检测方法的漏洞。如果你有这样的方法,不妨分享出来,一起学习学习吧。
    当然,我们还可以将程序设计为不依赖状态的执行成功与否。也就是不检测更新是否成功。一般情况下,数据库都会执行成功,所以状态更新不必做成功与否的检测。而且因为状态是周期性的更新,如果每一次都检测,对性能也造成了影响。
    当然,具体应该采取哪种策略,还是需要结合具体的应用场景来讲。
    本次的分享就是将这个问题分享出来,没有什么高深的,仅供初学者们参考,大神勿喷。