|
|
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
Здравствуйте, уважаемые SQL-разработчики. С Наступающим Новым годом Вас! У меня вопрос, пусть тривиальный, но все же актуальный... Нужно организовать простейший биллинг. Отслеживать баланс пользователя, поступления на счет и списание средств. Без использования триггеров. У меня есть два варианта, помогите выбрать оптимальный. 1-й Вариант. Есть таблицы: - Пользователи, - Текущий баланс пользователя, - Операции Таблица "Операции" содержит поля (ID int identity(1,1) PK, Summ real, Operation bit, DateOperation datetime default(getdate())). Поступления на счет имеют Operation - 1, списания Operation - 0. Баланс считается каждые 0,5 минуты. То есть, операция списания, вставляется в базу каждые 0,5 минут, при этом могут быть параллельные транзакции, если пользователи параллельно звонят кому-то, возможно транзакции будут блокировать друг друга. При списании денег, пересчитываем баланс за последний месяц (или другой период) и фиксируем в таблице "Текущий баланс пользователя". Если баланс пользователя меньше чем стоимость звонка на 0,5 минут, блокируем пользователя (ставим метку в таблице "Пользователи"). 2-й Вариант. Есть таблицы: - Пользователи, - Операции - Операции (архив) Таблица "Операции" содержит поля (ID int identity(1,1) PK, Summ real, Operation bit, DateOperation datetime default(getdate())). Поступления на счет имеют Operation - 1, списания Operation - 0. Баланс считается каждые 0,5 минут. Операция списания вставляется в базу каждые 0,5 минут, при этом могут быть параллельные транзакции, если пользователи параллельно звонят кому-то, возможно таблицы будут заблокированы. При списании денег, пересчитываем на лету баланс. Если баланс пользователя меньше чем стоимость звонка на 0,5 минут, блокируем пользователя (ставим метку в таблице "Пользователи"). Вешаем JOB, который периодически переносит строки с таблицы "Операции" в таблицу "Операции (архив)". Баланс делаем как View или Function. Например, Код: plaintext Код: plaintext 1. Нужно чтобы работало быстро. Как быть, что делать и как правильно делать??? Спасибо за предложенные варианты! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 15:39 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
авторТаблица "Операции" содержит поля (ID int identity(1,1) PK, Summ real, Operation bit, DateOperation datetime default(getdate())). Забыл поле. Извините! Таблица "Операции" содержит поля Код: plaintext 1. 2. 3. 4. 5. Модератор: Тема перенесена из форума "Microsoft SQL Server". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 15:42 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
nodir_azam...поступления на счет и списание средств. Без использования триггеров. У меня есть два варианта, помогите выбрать оптимальный. 1-й Вариант. ...Баланс считается каждые 0,5 минуты. ...при этом могут быть параллельные транзакции это нормальный вариант, если забыть, что нельзя использовать триггер и отказаться от "каждые 0,5 минуты". К сведению, блокировки при параллельных транзакциях - нормальное явление А вот это явное противоречие насчет "каждые 0,5 минут": nodir_azamОперация списания вставляется в базу каждые 0,5 минут, при этом могут быть параллельные транзакции... nodir_azam2-й Вариант... ...При списании денег, пересчитываем на лету баланс. ...Нужно чтобы работало быстро... это вообще не вариант для online, тем более что четко не сформулирован. (честно говоря, не встречал еще реального процесса, который бы просто генерил сразу одну окончательную операцию списания, так как в жизни возможны отмены транзакций) В вашем случае как раз два взаимосвязанных объекта: набор операций и их агрегация в виде суммы. Более того, вами не допущен вариант отрицательного баланса, т.е. на каждую операцию списания нужна проверка и изменение в одной транзакции, которая и обеспечит целостность. Другое дело, что транзакции по разным пользователям логически не должны блокировать друг друга никогда - это первое возможное ускорение. Второе, согласно отсутствию отрицательного баланса, транзакция списания со счета может быть прервана, отменяя предоставление услуги, что нужно учитывать при разработке. Так как вы не указали версию ПО, думаю, вам лучше перейти с данным вопросом в "Проектирование" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 16:14 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
vino, Да прошу прощения. Ладно, задам вопрос по другому. Биллинг учитывает стоимость звонков Web-call. Фактически участвуют в диалоге две "ноги". "Нога-1" от сервера до телефона самого пользователя, который совершает звонок, "Нога-2" до конечного телефона (абонента). Последовательность вызовов при звонке следующая: 1. Старт задачи звонка, посылается запрос с идентификатором абонента (acc1@domain1) и телефоном From в e.164 (+7495123456) и телефоном To в e.164 (+4887585576). Биллинг возвращает возможность такого звонка (если денег у инициатора хватит денег хотя бы на минуту). 2. Стартует звонок на телефон From. Пользователь поднимает трубку. Посылается запрос в биллинг START1. 3. Далее, каждые пол минуты, посылается в биллинг запросы PING1 (возвращается ответ - 1, можно продолжать звонок, 0 - средства на исходе, прерываем). 4. Если пользователь в этот момент бросил трубку, посылается запрос END1 (Биллинг считает окончательную стоимость звонка). 5. Стартует звонок на телефон To. Абонент (конечный пользователь) поднимает трубку. Посылается запрос START2. 6. Далее каждые пол минуты посылается запрос PING2.(возвращается ответ - 1, можно продолжать звонок, 0 - средства у инициатора звонка на исходе, прерываем) 7. Окончание разговора с любой стороны, посылка запроса END2. Как эту логику перенести в таблицы БД. Сервер Windows, БД - MS SQL 2005 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 16:24 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
допишу, каждые 0,5 минут, кроме записи в таблицу о списании средств, надо отдавать для IP PBX ответ, прерывать звонок или продолжать, есть деньги на счету или нет... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 16:33 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
Предлагаю начать с решения задачи в лоб (самым простым способом) мне больше нравится вариант 2 Единственное я не понял зачем нужен Operation bit, почему это не регулируется знаком Summ Второе тип данных у summ лучше объявить int и считать баланс в копейках (милликопейках) Третье зачем параметр типа даты в select * from dbo.GetBalance(@DateTime) там должен быть код абонента @UserId int Код: plaintext 1. 2. 3. 4. 5. Нужна таблица Звонки То есть 1. Старт задачи звонка, посылается запрос с идентификатором абонента (acc1@domain1) и телефоном From в e.164 (+7495123456) и телефоном To в e.164 (+4887585576). Запрашиваем dbo.GetBalance(@UserId int) Заначиваем тариф (сумма списания за полминуты разговора), оно нам скорее всего понадобится Вставляем в таблицу звонков 2. Стартует звонок на телефон From. Пользователь поднимает трубку. Посылается запрос в биллинг START1. Транзакция Вставляем строчку со списанием за полминуты (минуту) разговора (сумма была рассчитана заранее чтобы не тормозить транзакцию) и кодом звонка Запрашиваем dbo.GetBalance(@UserId int) Коммит 3. Далее, каждые пол минуты, посылается в биллинг запросы PING1 (возвращается ответ - 1, можно продолжать звонок, 0 - средства на исходе, прерываем). Транзакция Вставляем строчку со списанием за полминуты (минуту) разговора Запрашиваем dbo.GetBalance(@UserId int) Коммит 4. Если пользователь в этот момент бросил трубку, посылается запрос END1 (Биллинг считает окончательную стоимость звонка). Обновляем таблицу звонков Считаем сумму операций по конкретному звонку. 5,6,7 Аналогично Такая схема УЖЕ должна обеспечить приемлимую производительность, но ее можно улучшить В свободное время (раз в день, месяц, год) можно заменить блок записей у абонента на одну - входящее сальдо и переместить его (блок) в архив. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 18:22 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
SERG1257, Я сделал так Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. Забил 4 пользователей и 500 000 операций ... работает шустро... может можно лучше??? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 18:42 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
теперь надо все это привязать к вызовам со стороны телефонии... не забыть про таблицу тарифов... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 18:46 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
жаль нельзя редактировать посты, не те таблицы привёл Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 18:54 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
Хозяин барин. Вы 1 считаете баланс ДВА раза 2 при подсчете баланса возитесь с датой 3 обновляете таблицу пользователей с текущим денормализованным балансом, то есть принимаете на себя всю транзакционную головную боль 4 неправильно именуете функции (UserPayment ну никак не похоже на списание) 5 ведете нарастающий итог (это задача отчета) nodir_azam Забил 4 пользователей и 500 000 операций ... работает шустро... Самое веселое когда тонны пользователей одновременно пытаются вставлять/обновлять nodir_azam может можно лучше???Как лучше на мой взгляд я отвечал выше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 19:01 |
|
||
|
Как лучше организовать баланс пользователя
|
|||
|---|---|---|---|
|
#18+
SERG1257, Согласен... Ну с датой вожусь, потому что мне не нужна вся история пользователя, а только от последнего пополнения, и нарастающий итог тоже для этого Есть альтернативное решение как исключить не нужную историю операций? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.12.2009, 19:06 |
|
||
|
|

start [/forum/topic.php?fid=32&msg=36394513&tid=1542912]: |
0ms |
get settings: |
10ms |
get forum list: |
18ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
201ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
63ms |
get tp. blocked users: |
1ms |
| others: | 244ms |
| total: | 556ms |

| 0 / 0 |
