@palnamalina said in Как включить пересылку в Gmail?:
Актуально
https://community.bablosoft.com/topic/24964/bas-не-открывает-всплывающую-диалоговую-страницу/28
Как вариант сделай поле Лок. И сразу за селектом делай запись в лок, а дальше хоть вечность над ней трудись, другие не тронут, потому что Лок.
Точнее наоборот - сначало лок
@Shogo said in Как в SQL сделать сразу несколько запросов в одном действии:
@Bigma вы опять о том же - пример для того чтобы максимально упросить запрос, напиши я сложный - вариантов дискуссии было бы больше, а пришло бы к тому же - что там доли секунды )
Если что-то работает не как ожидается, то ищется work around. В случае с select и потом delete он есть. Я не уверен, что нет универсального обходного пути на "ну непременно хочу делать два запроса сразу". Ну не работает оно вот как ты хочешь.
Вариантов тут два:
Если нужна какая-то консистентность запросов, есть транзакции. Все равно в пачке запросов, что идут друг за другом, нет никаких гарантий. А в транзакциях есть.
Есть еще вариант хранимых процедур на стороне движка базы данных, тогда дергание чего-то в запросе это одна строчка, а под капотом целая бизнес логика может быть.
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
@sergerdn Вы прям сильно завернули, банковские операции тут что-ли 😂 ну тогда уже рабочий пример в студию, мне тоже стало интересно.
Чего пример? Еще есть функции в базе данных, они могут вернуть данные, а процедуры нет.
https://stackoverflow.com/questions/3744209/mysql-stored-procedure-vs-function-which-would-i-use-when
Я имел ввиду пример скрипта, шаг за шагом, тут 99 % в первые мускуль поставили.
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
Я имел ввиду пример скрипта, шаг за шагом, тут 99 % в первые мускуль поставили.
Так по ссылке есть конкретный пример шаг за шагом.
CHAR(20)).SELECT hello(name) FROM names;) и получаем ожидаемый результатCREATE FUNCTION hello (s CHAR(20))
RETURNS CHAR(50) DETERMINISTIC
RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec)
CREATE TABLE names (id int, name varchar(20));
INSERT INTO names VALUES (1, 'Bob');
INSERT INTO names VALUES (2, 'John');
INSERT INTO names VALUES (3, 'Paul');
SELECT hello(name) FROM names;
+--------------+
| hello(name) |
+--------------+
| Hello, Bob! |
| Hello, John! |
| Hello, Paul! |
+--------------+
3 rows in set (0.00 sec)
@sergerdn Честно говоря не понял.
Задача такая. Есть многопоток. Каждый поток пытается ухватить запись, и чтоб другие ее не трогали.
Мой вариант - сразу лочить не залоченную запись. И дальше с ней работать.
Ваш вариант проще?
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
@sergerdn Честно говоря не понял.
Задача такая. Есть многопоток. Каждый поток пытается ухватить запись, и чтоб другие ее не трогали.
Мой вариант - сразу лочить не залоченную запись. И дальше с ней работать.
Ваш вариант проще?
Есть очень простой вариант делать SELECT FOR UPDATE .
То есть:
used, по умолчанию 0used 0 и СРАЗУ в это же запросе менять used на 1. Это как раз делает SELECT FOR UPDATE .Я так делал, там будут нюансы, связанные с множеством блокировок, но если нет стопицот запросов в секунду, они будут незаметны. Так как SELECT FOR UPDATE залочит всю таблицу на INNODB.
https://dev.mysql.com/doc/refman/8.0/en/select.html
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
@sergerdn Жесть, а зачем всю таблицу то лочить? Я привел пример с полем, когда вообще ничего не лочится. Просто запись выподает из выборки остальных запросов...
Ну оно вот так работает, точнее работало когда то. Сейчас не могу ручаться на 100%. В сфере применения BAS это будет незаметно, так как лок таблицы на наносекунду по время выполнения запроса не повлияет ни на что.
Таблица лочится ТОЛЬКО на время выполнения одного запроса, чтобы взять запись и поменять у нее поле. Как раз, чтобы другие потоки не схватили ее же. Вариантов тут нет, надо лочить.
Может сейчас лочится только конкретная запись, не вся таблица. Пойду как я сам доки почитаю.
Ты дал вариант, при котором другие потоки все таки могут схватить нужную запись.
Поток 1:
А между этими пунктами поток 2 успел схватить ее. Это все ненадежно и добавляет свою логику, вместо SELECT FOR UPDATE, который был придуман ради этого.
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
@sergerdn Жесть, один поток повис, а вся таблица залочена. Это прям майсами какое то...
Сам запрос повис что ли? В честь чего он "повиснет"? И блокировки делаются во время выполнения запроса, когда сам БД его выполняет, а не когда ты его послал.
Спорить не буду, но по мне, проще запись лочить в отдельном поле. Сразу записали, что она не доступна, и дальше делаем что хотим. Переодически после остановки чистить, чтоб хвостов при отвалах не было.
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
Спорить не буду, но по мне, проще запись лочить в отдельном поле. Сразу записали, что она не доступна, и дальше делаем что хотим. Переодически после остановки чистить, чтоб хвостов при отвалах не было.
Логика, что ты предложил, работает не так, как ты от нее ожидаешь. Другие потоки могут схватить запись в ненужный тебе момент. Я отредактировал комментарий выше, где описал ситуацию. Ты фактически пытаешься сделать в коде то, что было уже придумано разработчиками БД.
Все мы строим велосипеды, это частое явление.
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
@sergerdn В смысле? Если запрос идёт с проверкой на поле Лок? Каждый запрос многопотока - проверяет есть ли в поле Лок 1 - они все в очереди. Первый записал, второй не взял....
Есть вариант, что я неправильно тебя понял. Напиши последовательность sql запросов.
Обновляем запись в которой поле Лок =0 меняем на 1, в ответе получили айди записи? Все делаем с ней что хотим. Другой поток ее уже не трогает, так как она не попадает в условие выборки.
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
Обновляем запись в которой поле Лок 0 меняем на 1, в ответе получили айди записи? Все делаем с ней что хотим. Другой поток ее уже не трогает, так как она не попадает в условие выборки.
Дай пример запроса UPDATE, где ты в ответе получаешь id обновленной записи. Потому что у меня какая-то другая БД.
MariaDB [wordpress]> select * from wp_users;
+----+------------+------------------------------------+---------------+--------------------+-------------------------+---------------------+---------------------+-------------+--------------+
| ID | user_login | user_pass | user_nicename | user_email | user_url | user_registered | user_activation_key | user_status | display_name |
+----+------------+------------------------------------+---------------+--------------------+-------------------------+---------------------+---------------------+-------------+--------------+
| 1 | moderator | $P$B/qpWWZ5C./khtr3h03W5S2sEbvW/ | moderator | ghtrhgtrhtrhtr@gmail.com | https://coolwp.com | 2021-11-12 21:16:43 | | 0 | moderator |
+----+------------+------------------------------------+---------------+--------------------+-------------------------+---------------------+---------------------+-------------+--------------+
1 row in set (0.000 sec)
MariaDB [wordpress]> update wp_users set user_email="blaaaa@local";
Query OK, 1 row affected (0.001 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [wordpress]>
@Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:
@sergerdn индекс есть?
CREATE TABLE `wp_users` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_login` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`user_pass` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`user_nicename` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`user_email` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`user_url` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`user_registered` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`user_activation_key` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`user_status` int(11) NOT NULL DEFAULT 0,
`display_name` varchar(250) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (`ID`),
KEY `user_login_key` (`user_login`),
KEY `user_nicename` (`user_nicename`),
KEY `user_email` (`user_email`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci