lamport逻辑时钟_逻辑与物理时钟乐观锁定

lamport逻辑时钟

介绍

在我以前的文章中,我演示了为什么乐观锁定是应用程序级事务唯一可行的解​​决方案。 乐观锁定要求版本列可以表示为:

  • 物理时钟(从系统时钟获取的时间戳值)
  • 逻辑时钟(递增的数值)

本文将说明为什么逻辑时钟更适合于乐观锁定机制。

系统时间

系统时间由操作系统内部时钟算法提供。 可编程间隔计时器定期发送中断信号(频率为1.193182 MHz)。 CPU接收时间中断并增加一个滴答计数器。

Unix和Window都将时间记录为自预定义的绝对时间参考(纪元)以来的滴答数。 操作系统时钟分辨率从1ms(Android)到100ns(Windows)和1ns(Unix)不等。

单调时间

要订购事件,版本必须单调前进。 虽然增加本地计数器是单调函数,但是系统时间可能并不总是返回单调时间戳。

Java有两种获取当前系统时间的方法。 您可以使用:

    1. System#currentTimeMillis() ,它提供自Unix纪元以来经过的毫秒数。此方法不会给您单调的时间结果,因为它返回的墙上时钟时间容易向前和向后调整(如果NTP用于系统时间)同步) 。对于单调的currentTimeMillis,你可以检查彼得Lawrey的解决方案或Bitronix事务管理单调时钟 。
    2. System#nanoTime() ,返回自任意选择的时间参考以来经过的纳秒数

此方法尝试使用当前的操作系统单调时钟实现,但是如果找不到单调时钟,它将回到挂钟时间 。

参数1:系统时间并非总是单调递增。

数据库时间戳精度

SQL-92标准将TIMESTAMP数据类型定义为YYYY-MM-DD hh:mm:ss。 小数部分是可选的,每个数据库都实现特定的时间戳数据类型:

关系数据库管理系统 时间戳分辨率
Oracle TIMESTAMP(9)最多可以使用9个小数位(纳秒精度)。
微软SQL DATETIME2的精度为100ns。
MySQL MySQL 5.6.4增加了对TIME,DATETIME和TIMESTAMP类型(例如TIMESTAMP(6))的微秒精度支持。
先前MySQL版本会丢弃所有时间类型的小数部分。
PostgreSQL TIME和TIMESTAMP类型都具有微秒精度。
DB2 TIMESTAMP(12)最多可以使用12个小数位(皮秒精度)。

关于持久性时间戳,大多数数据库服务器至少提供6个小数位。 MySQL用户一直在等待更精确的时间类型,而5.6.4版本最终增加了微秒精度。

在5.6.4之前MySQL数据库服务器上,更新可能会在任何给定的每秒生命周期内丢失。 这是因为所有更新同一数据库行的事务都将看到相同的版本时间戳(指向当前运行秒的开始)。

参数2:5.6.4之前MySQL版本仅支持秒精度时间戳。

处理时间不是那么容易

递增本地版本号始终更安全,因为此操作不依赖任何外部因素。 如果数据库行已包含更高版本号,则您的数据已过时。 就这么简单。

另一方面,时间是最复杂的维度之一。 如果您不相信我,请查看的夏令时处理注意事项 。

Java用了8个版本终于有了成熟的Date / Time API 。 跨应用程序层处理时间(从JavaScript到Java中间件再到数据库日期/时间类型)使情况变得更糟。

论据3:处理系统时间是一项具有挑战性的工作。 您必须处理leap秒 , 夏令时 , 时区和各种时间标准 。

分布式计算的经验教训

乐观锁定与事件排序有关,因此自然地,我们只对事前发生的关系感兴趣。

在分布式计算中,逻辑时钟优于物理时钟(系统时钟),因为网络时间同步意味着可变的延迟。

序列号版本控制类似于Lamport时间戳算法 ,每个事件仅增加一个计数器。

虽然Lamport时间戳是为多个分布式节点事件同步定义的,但数据库乐观锁定要简单得多,因为只有节点(数据库服务器)上的所有事务都是同步的(来自并发客户端连接)。

论据4:分布式计算比物理时钟更喜欢逻辑时钟,因为无论如何我们只对事件排序感兴趣。

结论

起初,使用物理时间似乎很方便,但事实证明这是一个幼稚的解决方案。 在分布式环境中,几乎不可能实现完美的系统时间同步。 总而言之,在实现乐观锁定机制时,您应该始终偏爱逻辑时钟。

翻译自: https://www.javacodegeeks.com/2014/10/logical-vs-physical-clock-optimistic-locking.html

lamport逻辑时钟

你可能感兴趣的:(数据库,分布式,java,mysql,python)