Генерация псевдо-Id в MySQL
Для начала оговорю рабочую среду: .net core + Entity Framework Core + MySQL.
Теперь к делу: в моей БД есть примерно следующая таблица:
(PK) Id:string // обыкновенный GUID
LocalId:int // Id, который будет видеть пользователь
// Основная проблема в том, что LocalId не уникален
(FK) UserId:int // Уникальна комбинация UserId-LocalId
OtherData:any
Простая авто-генерация не подходит вот почему: для каждого пользователя нужно поддерживать сплошную нумерацию. То есть не должно быть такого, что у первого пользователя LocalId идут 1-5, затем LocalId 6-10 второго пользователя, затем 11-n первого и так далее.
Два единственных варианта, которые я пока нашёл - это всё же костыли:
- Завести у пользователя поле
LastLocalId:int, и при добавлении данных (а они добавляются пачками по 100+ штук за раз) взять это значение, ручками наращиватьLocalIdдля каждой новой строки данных, а в конце последний получившийсяLocalIdзаписать вLastLocalId. Минус этого подхода я вижу в том, что если пользователь запустит 2 потока на добавление данных (к примеру, с разных устройств зайдёт), то один из потоков словит исключение (если не оба) - Перед добавлением данных глянуть на самый крупный
LocalIdдля пользователя, а дальше этот вариант ровно ничем не отличается от первого - ручное наращиваниеLocalId(пожалуй, единственное отличие, которое будет достигнуто - при удалении последней записи нумерация собьётся и последнийLocalIdповторится)
Проблему обоих вышеперечисленных способов (возможность словить исключение при попытке параллельно добавить данные) можно решить путём издевательства над БД - перед добавлением каждой строки в таблицу заново запрашивать LocalId (вместо того, чтобы пачкой добавить все данные)
Я полагаю, что я всё-таки не один такой человек, кому понадобился псевдо-Id. И надеюсь, что в MySQL придумали настройки, которые позволят реализовать нужный мне функционал более оптимизированно и потоко-безопасно
UPD: точная используемая версия БД - 10.3.17-MariaDB
Результат команды SHOW CREATE TABLE marketplacepurchases;:
CREATE TABLE `MarketplacePurchases` (
`Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
`LocalId` bigint(20) NOT NULL,
`OrderNumber` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`OrderDate` datetime(6) NOT NULL,
`Currency` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerAccount` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerFullName` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerFirstName` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerLastName` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerAddressStreet` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerAddressZipCode` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerAddressCity` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerAddressCountry` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerAddressCountryCode` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`SellerEmail` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerAccount` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerFullName` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerFirstName` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerLastName` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerAddressStreet` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerAddressZipCode` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerAddressCity` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerAddressCountry` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerAddressCountryCode` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`BuyerEmail` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`PaidDate` datetime(6) DEFAULT NULL,
`RequestedDate` datetime(6) DEFAULT NULL,
`ShippedDate` datetime(6) DEFAULT NULL,
`GoodsRecieveDate` datetime(6) DEFAULT NULL,
`CompletedDate` datetime(6) DEFAULT NULL,
`ArchivedDate` datetime(6) DEFAULT NULL,
`Note` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`ShippingMethod` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`ShippingCost` float NOT NULL,
`PaymentMethod` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`TotalAmountWithoutShipping` float NOT NULL,
`TotalAmountWithShipping` float NOT NULL,
`ListingFormat` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`CreatedDate` datetime(6) NOT NULL,
`LastModifedDate` datetime(6) NOT NULL,
`MarketplaceLastModifedDate` datetime(6) NOT NULL,
`OrderStatus` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`PaymentStatus` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
`UserMarketplaceDataId` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL,
PRIMARY KEY (`Id`),
KEY `IX_MarketplacePurchases_UserMarketplaceDataId_LastModifedDate` (`UserMarketplaceDataId`,`LastModifedDate`),
CONSTRAINT `FK_MarketplacePurchases_UserMarketplaceDatas_UserMarketplaceDat~` FOREIGN KEY (`UserMarketplaceDataId`) REFERENCES `UserMarketplaceDatas` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8