2013-03-31 4 views
0

Я разрабатываю приложение учета, где каждому транзакциям предоставляется ключ. , например: в сделке купли-продажи есть две записи, одна для продажи и другая для клиента.

Как исправить эту проблему внешнего ключа MySQL?

ID       | trid | Дата                     | Счет                       | Сумма


112 | 33 | 01-04-2013 | Продажа A \ c                   | 300.00
113 | 33 | 01-04-2013 | Заказчик A \ c     | 300.00
114 | 34 | 01-04-2013 | Продажи A \ C                   | 110,00
115 | 34 | 01-04-2013 | Клиент 1 A ​​\ c | 110.00
116 | 35 | 01-04-2013 | Продажа A \ c                     | 250.00
117 | 35 | 01-04-2013 | Клиент 2 A \ c | 250.00

здесь, TRID MAX (TRID) + 1. Эта концепция отлично работает в среде с одним пользователем, но в многопользовательской среде, где приложение используется одновременно несколькими пользователями, один или несколько пользователей могут получать одинаковые TRID.

Что может быть для этого решением?

+0

Не можете ли вы использовать GUID для TRID? – aguyngueran

ответ

3

Вам необходимо использовать транзакцию и заблокировать таблицу во время использования, чтобы создать атомную операцию - это гарантирует, что ни один из двух процессов не будет использовать одно и то же значение.

Вам нужно поставить процедурный вместе, но в основном это:

-- start transaction 
-- lock table 
-- select max(trid) + 1 and store in a variable 
-- do your inserts 
-- unlock table 
-- end transaction 
+0

Что произойдет, если таблица заблокирована, а другой пользователь пытается вставить запись? –

+0

Им нужно просто дождаться завершения транзакции, прежде чем она позволит им получить доступ к таблице. Я не ожидал бы никаких проблем, пока ваша транзакция будет оставаться быстрой. Но определенно проверьте это, возможно, запустите «SLEEP» в транзакции, чтобы заставить ее занять много времени, а затем, пока она спит, попытайтесь поразить ее несколько раз и убедитесь, что они изящно ждут завершения транзакции, а не ошибки , –

+0

будут ли данные доступны для целей readonly, пока они заблокированы? –

1

Прежде всего, если в одиночку TRID должен быть уникальным, то сделать это ключ (в одиночку, а не в сочетании с некоторыми другое поле). Таким образом, СУБД не допускает ввода дубликатов в базу данных, независимо от того, какие ошибки вы делаете в клиентском коде.

В многопользовательской среде вы можете использовать auto-increment для безопасного создания уникальных значений, при условии, что вы не заботитесь о том, чтобы сгенерированные значения были смежными.

Ото, если вы не можете позволить себе «дыры», то:

  • либо заблокировать всю таблицу перед тем SELECT MAX(TRID) + 1,
  • или сделать то же SELECT без блокировки, но быть готовым повторно попробовать, если есть ключевое нарушение.

Я бы рекомендовал против блокировки, если вы можете ему помочь, поскольку это может иметь серьезные негативные последствия для масштабируемости.

+0

Вы можете указать код? Я попробовал этот http://stackoverflow.com/questions/15749752/lock-table-after-begintransaction-mysql-transaction-in-c-net, но все еще не работал. транзакция не блокирует таблицу. –

+0

@NitinKabra Связанное сообщение не содержит кода блокировки. Вам нужно будет сделать: ['LOCK TABLES your_table WRITE'] (http://dev.mysql.com/doc/refman/5.6/en/lock-tables.html). ПРИМЕЧАНИЕ. Вам нужно будет заблокировать всю таблицу, поэтому просто «SELECT ... FOR UPDATE» недостаточно. –

Смежные вопросы