PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_mysql

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_mysql_02PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_字段_03

事情的发生时这样的,在很久很久以前,SQL SERVER 有一个字段类型叫timestamp, 对比其他数据库都没有的 row version 自动化管理的东西。这个东西厉害的地方,虽然看上去可能是一个时间字段,但实际上不是,只要你对SQL SERVER 表的任意一行进行变动,那你放心那个字段的值一定会自动变化,这样你就可以通过这个字段,在程序里面先将这行的 timestamp值取出来,然后根据业务逻辑,如果需要过段时间你再去这一行变化或曾经变化过吗?之间与现在的timestamp字段值进行比对,那妥妥的能告诉你,这行的数据任意字段是否变化过,有人说MYSQL也有timestamp ,那个字段是通过时间来update 只要这个行变动过就触发timestamp 更改时间就可以了,当然datetime也行,早期版本不行。


我只能用哼的一声回敬, too young to simple.  人家sql server 的字段不是时间,人家不存在你并发高然后给出的,毫秒,微妙之类可能重复的可能性,因为人家是唯一值,一串人类不懂的二进制。

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_字段_04

所以MYSQL 用了timestamp 然后还得搭上一个触发器,然后还不一定准。


所以就这样了,NO NO NO 

只要知道大致的原理,PostgreSQL ,MYSQL 统统的可以活学活用,做我们自己的 row  version management. 


这里先说PG ,PG 要比MYSQL 方便的多,因为天生的基因,让他做这个事情,很简单。PG的行版本管理是基于system column 其中有一个字段是ctid


以下是官方文档


PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_字段_05

意思就是这个ctid 字段在表里面行版本表示这一个行的物理位置。请注意,虽然可以使用ctid非常快速地定位行版本,但是如果更新或移动了某个行的ctid,它就会发生变化。因此,ctid作为长期行标识符是无用的。应该使用OID,或者用户定义的序列号来标识逻辑行。


所以呢,我们要的就是你的这个可以快速定位以及如果更新了,或移动了某个行的ctid 就会变化值。这就等同于 ,postgresql 天生在每个行上都给你做了一个GPS, 然后只要update ,或者数据移动了,例如copy 一个表到另一个地方等等的情况。那这个ctid 就会变化。 

可以看下面的图

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_字段_06

通过这个系统自带的ctid 可以很清楚,在这个行上到底做过UPDATE 操作没有,只要做了,并且是更新的值和原有的值一样的情况下,也会更新这个值。

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_字段_07

从这里也就泄露了一些PG的原理。


所以PG 的行版本管理就如此简单的比SQL SERVER 还简单的完成了,并且性能还要高,这是原生的。只要每次获得你关心这行的 ctid 然后在你想使用它的时候,在取一次值,相同那一定这一行是没有动过,也就证明了你关心的那个字段一定也没有变化。


下面轮到MYSQL 了,实际上MYSQL 本身的不具备POSTGRESQL 这样的物理定位的标记,同时也没有SQL SERVER 那样的timestamp 字段。可使用MYSQL 的人们一贯的心灵手巧,多动多思,也有办法。


实际上 sql server timestamp 想当于给一个表添加了一个计数器,针对每一行, 而Postgresql 是每一行有一个 "GPS" 定位系统。  

MYSQL 我们可以

1  和开发团队定义一个判断一行的字段变化的显示值,也就是要添加一个字段,来模拟sql server 的timestamp 这个字段,具体用什么类型,插入什么值,需要和开发团队来商量


2 在任何的DML 语句中,只要有UPDATE 就需要附带对这个字段的更新


我们看一下,我们要对当前的表添加一个字段,具体是什么字段类型不重要,这里只是模拟一下。checksum 就是那个添加的字段 binary

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_sql_08

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_mysql_09

在添加了字段后,我们对任何值的变动都会将附加字段的值进行变更,为了规范可以用一个函数,(函数的质量要高,否则可能会影响性能)

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_mysql_10

我们可以看一下结果,为什么选择这个怪异的东西,原因是不会有人“失误”的来更改我们的checksum  字段来避免一些“人为的错误”。

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_sql_11


通过上面的一些东西,也可以看出每种数据库其实都有自己的特点,掌握了原理,并且能模拟原理,就可以弥补一些本身不提供的功能,或者与生俱来的特异功能。


或许有人说,干嘛不给MYSQL 设置 default value 然后这样我就不用去insert  的时候还要带那个字段,或者在回到使用触发器之类的。


1 使用MYSQL 是为了更高的并发,使用触发器不适合我们的初衷


2 如果设置了某些默认值,并且在非单库的情况下,会有类似的error提示

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_mysql_12


总结,要简单有postgresql体贴入微, 要自己动手有 mysql 勤劳能丰衣足食,So as the tree, so the fruit.

PostgreSQL  MySQL 行版本管理 PK SQL SERVER timestamp 行版本管理_sql_13