18位身份证号的编码规则

突然有一个疑问,身份证号码是如何编码的?最主要是如何避免身份证号重复的(同一个行政区域内的同年同月同日生的同性别的新生儿)?

18位身份证号编码规则

知乎的一篇博文实名认证前传之身份证号码编码规则 感觉已经说得很清楚了,用我自己的身份证号测试了一下,最后一位的校验码的规则应该是对的。

下面的内容均来自这一篇博文。

一、身份证号码结构

早期‘身份证号码’叫‘社会保障号’,为15位,1999年开始更名为公民身份证号码,即第二代身份证,为18位,且终身不变。

430512198908131367

公民身份号码是特征组合码,由前十七位数字本体码和最后一位数字校验码组成。排列顺序从左至右依次为六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

地址码: 6位,表示编码对象常住户口所在县(市、旗、区)的行政区划代码。对于新生儿,该地址码为户口登记地行政区划代码。需要没说明的是,随着行政区划的调整,同一个地方进行户口登记的可能存在地址码不一致的情况。行政区划代码按GB/T2260的规定执行。

出生日期码:8位,表示编码对象出生的年、月、日,年、月、日代码之间不用分隔符,格式为YYYYMMDD,如19880328。按GB/T 7408的规定执行。原15位身份证号码中出生日期码还有对百岁老人特定的标识,其中999、998、997、996分配给百岁老人。

顺序码: 3位,表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

校验码: 1位,根据本体码,通过采用ISO 7064:1983,MOD 11-2校验码系统计算出校验码。算法可参考下文。前面有提到数字校验码,我们知道校验码也有X的,实质上为罗马字符X,相当于10.

校验码算法

校验码是通过前 17 位数字通过下面这个算法进行计算得到的,也就是说前 17 位数字确定了,第 18 位数字也就确定了。

举个例子,假设本体码为 11010519491231002

第一步:根据下表,将本体码的前17位数字乘以相应的加权因子,求和,按上面的例子,就是 $1 \times 7+1 \times 9+ \cdots +2 \times 2 = 167 $

身份证位置序号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
加权因子 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2

第二步,对上面的和除以11计算余数,这里就是

第三步,根据余数对照下面,最终得到校验码为 X

余数 0 1 2 3 4 5 6 7 8 9 10
校验码 1 0 X 9 8 7 6 5 4 3 2

因此,本例的完整身份证号为 11010519491231002X

如何避免重复呢?

我的问题是,同一个县同一天肯定不只是一个人出生(顺序码从 000 到 999 一共是1000个数,也就是一个县同一天能落户的新生儿数目的最大值是 1000 ),同一个县可以用于落户的派出所应该有多个,那么同一天同一性别的多个初生儿同时分别去多个派出所落户,是如何确保他们分配得到的身份证号是唯一的呢?

这个问题我不知道,但是我感觉这应该是数据库的一个操作。我能想到的是,可能在同一个县里如果有人新建记录的时候就锁住数据库,不允许其他人再往数据库里插入记录,这样就可以避免身份证号的重复问题。

然后我咨询了一下小强,他和我说这就是数据库的一个基本特性,如果有多个人同时往数据库里插入了主键相同的一行,那么应该有一个人会插入成功,其他人会显示失败。

数据库事务

下面的内容主要来自维基百科 数据库事务

数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。

概要

数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的:

  1. 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
  2. 当多个应用程序并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

当事务被提交给了数据库管理系统(DBMS),则DBMS需要确保该事务中的所有操作都成功完成且其结果被永久保存在数据库中,如果事务中有的操作没有成功完成,则事务中的所有操作都需要回滚,回到事务执行前的状态;同时,该事务对数据库或者其他事务的执行无影响,所有的事务都好像在独立的运行

例子

某人要在商店使用电子货币购买100元的东西,当中至少包括两个操作:

  1. 该人帐户减少100元
  2. 商店帐户增加100元

支援交易的资料库管理系统transactional DBMS)就是要确保以上两个操作(整个“交易”)都能完成,或一起取消;否则就会出现100元平白消失或出现的情况。

但在现实情况下,失败的风险很高。在一个数据库事务的执行过程中,有可能会遇上事务操作失败、数据库系统操作系统出错,甚至是存储介质出错等情况。这便需要DBMS对一个执行失败的事务执行恢复操作,将其数据库状态恢复到一致状态(数据的一致性得到保证的状态)。为了实现将数据库状态恢复到一致状态的功能,DBMS通常需要维护事务日志(英语:Transaction log)以追踪事务中所有影响数据库数据的操作[1][2]

ACID 性质

下文内容主要来自于 数据库的ACID(原子性、一致性、隔离性与持久性)

数据库管理系统中**事务(transaction)**的四个特性(分析时根据首字母缩写依次解释):原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

详解

  1. 原子性

原子性是指事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。

可采用“A向B转账”这个例子来说明解释

在DBMS中,默认情况下一条SQL就是一个单独事务,事务是自动提交的。只有显式的使用start transaction开启一个事务,才能将一个代码块放在事务中执行。

新增解释,根据 数据库事务原子性、一致性是怎样实现的? - 左轻侯的回答 - 知乎

为了实现原子性,需要通过日志:将所有对数据的更新操作都写入日志,如果一个事务中的一部分 操作已经成功,但以后的操作,由于断电/系统崩溃/其它的软硬件错误而无法继续,则通过回溯日志,将已经执行成功的操作撤销,从而达到 “全部操作失败" 的目的。最常见的场景是,数据库系统崩溃后重启,此时数据库处于不一致的状态,必须先执行一个crash recovery的过程:读取日志 进行REDO(重演将所有已经执行成功但尚末写入到磁盘的操作,保证持久性),再对所有到崩溃 时尚末成功提交的事务进行UNDO (撤销所有执行了一部分但尚末提交的操作,保证原子性)。 crash recovery结束后,数据库恢复到一致性状态,可以继续被使用。

  1. 一致性

一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。

如A给B转账,不论转账的事务操作是否成功,其两者的存款总额不变(这是业务逻辑的一致性,至于数据库关系约束的完整性就更好理解了)。

保障机制(也从两方面着手):数据库层面会在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,check约束等)和触发器设置;此外,数据库的内部数据结构(如 B 树索引或双向链表)都必须是正确的。业务的一致性一般由开发人员进行保证,亦可转移至数据库层面。

  1. 隔离性

多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。

在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。

事务最复杂问题都是由事务隔离性引起的。完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能。关于隔离性中的事务隔离等级(事务之间影响),参见相应博文

这里解释的还不够细,当存在并发操作时,原子性并不能保证一致性,因此引入了隔离性。详细回答见 数据库事务原子性、一致性是怎样实现的? - 左轻侯的回答 - 知乎

下面最核心的话是,多个事务并发执行后的状态,和它们串行执行后的状态是等价的。如何实现隔离性很复杂,但是我也不太关心。

但是,原子性并不能完全保证一致性。在多个事务并行进行的情况下,即使保证了每一个事务的原 子性,仍然可能导致数据不一致的结果。例如,事务1需要将100元转入帐号A: 先读取帐号A的 值,然后在这个值上加上 100 。但是,在这两个操作之间,另一个事务 2 修改了帐号 的值,为它增 加了100元。那么最后的结果应该是A增加了200元。但事实上,事务1最终完成后,帐号A只增加 了100元,因为事务2的修改结果被事务1覆盖掉了。
为了保证并发情况下的一致性,引入了隔离性,即保证每一个事务能够看到的数据总是一致的,就好象其它并发事务并不存在一样。用术语来说,就是多个事务并发执行后的状态,和它们串行执行后的状态是等价的。怎样实现隔离性,已经有很多人回答过了,原则上无非是两种类型的锁:
一种是悲观锁 ,即当前事务将所有涉及操作的对象加锁,操作完成后释放给其它对象使用。为了尽 可能提高性能,发明了各种粒度(数据库级/表级/行级…)/各种性质(共享钓/排他锁/共享意向 锁/排他意向锁/共享排他意向锁…) 的锁。为了解决死锁问题,又发明了两阶段锁协议/死锁检测 等一系列的技术。
一种是乐观锁,即不同的事务可以同时看到同一对象 (一般是数据行) 的不同历史版本。如果有两 个事务同时修改了同一数据行,那么在较晩的事务提交时进行冲突检测。实现也有两种,一种是通 过日志UND O的方式来获取数据行的历史版本,一种是简单地在内存中保存同一数据行的多个历 史版本,通过时间濯 来区分。
锁也是数据库实现中最复杂的部分之一。同样,如果涉及到分布式系统(分布式锁和两阶段提交是 分布式事务的基础),会比上述场景还要复杂得多。

  1. 持久性

这是最好理解的一个特性:持久性,意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。(完成的事务是系统永久的部分,对系统的影响是永久性的,该修改即使出现致命的系统故障也将一直保持)

write ahead logging:SQL Server中使用了WAL(Write-Ahead Logging)技术来保证事务日志的ACID特性,在数据写入到数据库之前,先写入到日志,再将日志记录变更到存储器中。

————————————————
版权声明:本文为CSDN博主「图灵的猫i」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39521554/article/details/80240841

身份证号码重复与隔离性

上面的身份证号码避免重复的问题就是用到了隔离性,如果我们把身份证号码设置位主键,那么往数据库中同时插入多个相同主键的行这一并发操作,按照隔离性的性质,和它们串行执行后的状态是等价的,也就是说最终应该是有一个插入操作成功,其他插入操作应该会报错,从而避免违背一致性,即数据库中出现重复的主键。

所以我的担心是多余的,数据库系统的基本特性本身就可以避免身份证号码重复这个问题的发生。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2019-2022 Vincere Zhou
  • 访问人数: | 浏览次数:

请我喝杯茶吧~

支付宝
微信