Royal Flash
-=MaestrO=-
Здравствуйте.
Помогите перейти на транзакции и блокировки строк в InnoDB с LOCK TABLES MyISAM
Я решил перейти на InnoDB с MyISAM.
Есть 3 таблицы в БД: balance_user, balance_log, balance_comment (комментарии к транзакциям по балансу, они могут быть, могут не быть, по этому заведена отдельная таблица).
Таблица balance_user:
| user_id | .... | balance_sum |
Т.е. в этой таблице хранятся суммы баланса пользователей. Каждому пользователю - одна строка.
Таблица balance_log
| id | user_id | sum | .... |
При приходе/расходе средств в balance_user изменяется значение колонки balance_sum для каждого пользователя. Причем, если с пользовательским балансом операция совершается впервые, в balance_user нужно добавить строку, если информация о балансе уже есть - обновить. В balance_log строки всегда только добавляются, т.е. эта таблица - журнал операций с балансом. В balance_comment строки могут быть добавлены или нет, в зависимости от наличия комментариев.
За один раз могут быть изменены балансы более одного пользователя.
На MyISAM все просто: в скрипте блокируются все 3 таблицы (LOCK TABLES ... WRITE), далее узнать MAX(id) balance_log, после сгененрировать sql-запросы insert/update для balance_user, создать insert для balance_log и, если требуется, insert для balance_comment.
И если с UPDATE все просто - сколько изменений в пользовательских балансах balance_user, столько и запросов UPDATE, то с INSERT немного сложнее: чтобы не заваливать БД пачкой запросов INSERT, все INSERT к одной таблице формируются в один запрос (INSERT INTO balance_log (id, user_id, sum) VALUES (1, 1, 30), (2, 195, 5598) ... ).
Поскольку после INSERT, в котором добавляется более одной строки, проблематично узнать ID созданный autoincremet для каждой строки, ID для balance_log формируется в скрипте, создающем запросы (для этого нужен первый запрос SELECT MAX(id) FROM balance_log).
По этому же ID balance_log привязывается и balance_comment.
Схема запросов MyISAM:
LOCK TABLES ... WRITE
SELECT MAX(id) FROM balance_log
// тут формируются запросы UPDATE/INSERT для balance_user и INSERT для balance_log, balance_comment
UPDATE balance_user SET balance_sum = 234 WHERE user_id = 1
UPDATE ...
INSERT INTO balance_user (user_id, balance_sum) VALUES (2, 304), (3, 58) , ...
INSERT INTO balance_log (id, user_id, sum) VALUES (1, 1, 30), (2, 195, 5598), ....
INSERT INTO balance_comment (balance_log_id, comment) VALUES (1, "Коментарий"), ....
UNLOCK TABLES
Подскажите, как переписать эту логику с учетом транзакций в InnoDB, чтобы блокировать не все таблицы, а только строки, с которыми будет проходить UPDATE и интервал ID, с которыми будет вставляться INSERT?
Помогите перейти на транзакции и блокировки строк в InnoDB с LOCK TABLES MyISAM
Я решил перейти на InnoDB с MyISAM.
Есть 3 таблицы в БД: balance_user, balance_log, balance_comment (комментарии к транзакциям по балансу, они могут быть, могут не быть, по этому заведена отдельная таблица).
Таблица balance_user:
| user_id | .... | balance_sum |
Т.е. в этой таблице хранятся суммы баланса пользователей. Каждому пользователю - одна строка.
Таблица balance_log
| id | user_id | sum | .... |
При приходе/расходе средств в balance_user изменяется значение колонки balance_sum для каждого пользователя. Причем, если с пользовательским балансом операция совершается впервые, в balance_user нужно добавить строку, если информация о балансе уже есть - обновить. В balance_log строки всегда только добавляются, т.е. эта таблица - журнал операций с балансом. В balance_comment строки могут быть добавлены или нет, в зависимости от наличия комментариев.
За один раз могут быть изменены балансы более одного пользователя.
На MyISAM все просто: в скрипте блокируются все 3 таблицы (LOCK TABLES ... WRITE), далее узнать MAX(id) balance_log, после сгененрировать sql-запросы insert/update для balance_user, создать insert для balance_log и, если требуется, insert для balance_comment.
И если с UPDATE все просто - сколько изменений в пользовательских балансах balance_user, столько и запросов UPDATE, то с INSERT немного сложнее: чтобы не заваливать БД пачкой запросов INSERT, все INSERT к одной таблице формируются в один запрос (INSERT INTO balance_log (id, user_id, sum) VALUES (1, 1, 30), (2, 195, 5598) ... ).
Поскольку после INSERT, в котором добавляется более одной строки, проблематично узнать ID созданный autoincremet для каждой строки, ID для balance_log формируется в скрипте, создающем запросы (для этого нужен первый запрос SELECT MAX(id) FROM balance_log).
По этому же ID balance_log привязывается и balance_comment.
Схема запросов MyISAM:
LOCK TABLES ... WRITE
SELECT MAX(id) FROM balance_log
// тут формируются запросы UPDATE/INSERT для balance_user и INSERT для balance_log, balance_comment
UPDATE balance_user SET balance_sum = 234 WHERE user_id = 1
UPDATE ...
INSERT INTO balance_user (user_id, balance_sum) VALUES (2, 304), (3, 58) , ...
INSERT INTO balance_log (id, user_id, sum) VALUES (1, 1, 30), (2, 195, 5598), ....
INSERT INTO balance_comment (balance_log_id, comment) VALUES (1, "Коментарий"), ....
UNLOCK TABLES
Подскажите, как переписать эту логику с учетом транзакций в InnoDB, чтобы блокировать не все таблицы, а только строки, с которыми будет проходить UPDATE и интервал ID, с которыми будет вставляться INSERT?