Mariadb

防止衝突數據,因為從導入的數據庫 MariaDB 中重複 id

  • January 25, 2018

我目前的 Web 應用程序有問題。我為某家公司製作了一個 Web 應用程序。我使用 CodeIgniter 3 製作了這個應用程序。

我使用 Maria DB 建構了數據庫。對於每個表中的 id,我為每個表的應用程序數據庫使用增量 ID。我通常將網路應用程序部署到雲伺服器(有時公司有自己的專用伺服器,但有時沒有)。有一天,有一家公司不想將我之前製作的應用程序部署到雲端(出於他們所說的安全目的)。

這家公司希望將應用程序部署到員工個人在辦公室的個人電腦上,而每個員工的個人電腦都沒有相互連接(即獨立的個人電腦/個人電腦/員工的筆記型電腦)。他們說,每5個月,他們會將員工個人電腦中的所有數據收集到公司的數據中心,當然數據中心沒有連接到網際網路。我告訴他們這不是儲存數據的好方法。(因為當我嘗試將所有數據合併為一個時,數據將是重複的,因為我的數據庫 ID 在增量 ID中)。當我的數據庫是增量 ID時, id 會崩潰。但是,公司仍然以這種方式製作應用程序,我不知道如何解決這個問題。

他們至少有 10 名員工會使用這個網路應用程序。據此,我必須親自將應用程序部署到 10 PC。

附加資訊:每個員工都有自己從公司獲得的唯一 ID

The study cases is what i describe below:

id   |  employee_id  | employee_name   |
1    | 156901010     |  emp1
2    | 156901039     |  emp2
3    | 156901019     |  emp3
4    | 156901015     |  emp4
5    | 156901009     |  emp5
6    | 156901038     |  emp6

問題是,每當他們從該應用程序填寫表格時,某些表並沒有儲存員工的 id,而是來自增量 id 的新 id。

例如**electronic_parts**表。它們具有如下屬性:

| id  |  electronic_part_name  |  kind_of electronic_part  |

如果員工 1 從 web 應用程序填寫表格,表格的內容如下所示。

| id  |  electronic_part_name  |  kind_of electronic_part  |
|  1  |   switch               |           1               |

如果員工 2 從 web 應用程序填寫表格,表格的內容如下所示。

| id  |  electronic_part_name  |  kind_of electronic_part  |
|  1  |      duct tape         |           10              |

當我嘗試將表的內容合併到數據中心時,它會因為重複的 id 而分崩離析。

一些選項:為每個使用者分配不同的 ID 範圍,使用複合主鍵,使用 UUID 或使用一些機制,使 auto_increment 功能能夠在主-主複製中使用:

  1. 在為每個員工的數據庫創建表時,可以指定不同的 AUTO_INCREMENT 位置,以便為每個員工分配一定範圍的 ID。例如
CREATE TABLE electronic_parts (
 id INT USIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
 electronic_part_name VARCHAR(40), 
 kind_of_electronic_part INT UNSIGNED
) AUTO_INCREMENT=1000;

可能不是一個好主意,因為沒有什麼可以阻止過分熱心的員工創建如此多的記錄以致最終進入其他人的範圍。(雖然我想你可以在你的應用程序中建立一個約束來避免這種衝突。)

  1. 重新設計主鍵,使它們成為具有一個自動遞增鍵和一個對每個員工都是唯一的鍵的複合鍵。例如。:
CREATE TABLE electronic_parts (
 id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
 employee_id INT UNSIGNED NOT NULL, 
 electronic_part_name VARCHAR(40), 
 kind_of_electronic_part INT UNSIGNED,
 PRIMARY KEY (id, employee_id) 
);

然後,您的應用程序必須使用每個員工的唯一值填充employee_id。例如:

INSERT INTO electronic_parts (
 employee_id, electronic_part_name, kind_of_electronic_part
) 
VALUES (156901010, 'switch', 1);

由於主鍵的自動遞增id組件,您不必擔心填充它。

一旦需要合併所有數據庫,一切都會好起來的,因為主鍵是由每個員工唯一的一個組件和每個單獨數據庫中唯一的一個組件組合而成的,因此這使得每個主鍵值在所有數據庫中都是唯一的。

我已經在 MariaDB 10.2 中成功測試了這一點。

  1. 使用UUID()UUID_SHORT()函式來生成全域唯一的主鍵,而不是自動遞增主鍵。然後,您的應用程序需要在創建記錄時顯式呼叫這些函式之一,或者您可以使用觸發器。(我個人認為以這種方式使用觸發器是糟糕的設計,但它確實有效。)
  2. 假設您知道將有多少使用者 (n) 的固定上限:您可以使用自動遞增主鍵並將auto_increment_increment設置為 n,然後將第一個使用者的auto_increment_offset設置為 0,第二個使用者設置為 1,第二個使用者設置為 2第三個使用者,以此類推。這樣,您將避免衝突,就像在 Galera 集群和其他主-主複製配置中使用 auto_increment 一樣。

引用自:https://dba.stackexchange.com/questions/196121