Гость
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Переполнился счетчик / 25 сообщений из 27, страница 1 из 2
27.02.2018, 09:38
    #39607624
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Есть некая система (если это важно, то UserSide), которая использует в качестве БД MySQL.
Есть самописный скрипт, который запускается каждые 5 минут и переносит в эту систему информацию из другой системы.
Используется запрос такого вида:
Код: sql
1.
2.
insert into tbl_base (`BILLCODE`,`CODETI`,`LOGNAME`,`PARENTCODE`,`NOTINBILLING`,`DATEADD`) values (?,?,?,?,null,now())
on duplicate key update `LOGNAME`=?,`PARENTCODE`=?,`NOTINBILLING`=null;


Таблица, соответственно, такая:
Код: sql
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.
CREATE TABLE `tbl_base` (
	`CODE` INT(11) NOT NULL AUTO_INCREMENT,
	`CODETI` VARCHAR(255) NULL DEFAULT NULL,
	`GROUPN` VARCHAR(38) NULL DEFAULT NULL,
	`ISREG` INT(1) NULL DEFAULT NULL,
	`LOGNAME` VARCHAR(255) NULL DEFAULT NULL,
	`DOGNUMBER` VARCHAR(255) NULL DEFAULT NULL,
	`DATEDOG2` VARCHAR(10) NULL DEFAULT NULL,
	`FIO` VARCHAR(255) NULL DEFAULT NULL,
	`PASS` VARCHAR(50) NULL DEFAULT NULL,
	`HOUSEC` INT(11) NULL DEFAULT NULL,
	`PODEZD` INT(3) NULL DEFAULT NULL,
	`HOUSECODE` VARCHAR(10) NULL DEFAULT NULL,
	`FLOOR` INT(3) NULL DEFAULT NULL,
	`APART` INT(11) NULL DEFAULT NULL,
	`APART_B` VARCHAR(32) NULL DEFAULT '',
	`EMAIL` VARCHAR(100) NULL DEFAULT NULL,
	`TEL` VARCHAR(255) NULL DEFAULT NULL,
	`TELMOB` VARCHAR(255) NULL DEFAULT NULL,
	`DOP` MEDIUMTEXT NULL,
	`DOP2` MEDIUMTEXT NULL,
	`BALANS` DOUBLE NULL DEFAULT NULL,
	`KREDIT` DOUBLE NULL DEFAULT NULL,
	`SKIDKA` INT(3) NULL DEFAULT NULL,
	`DATEPLUS` DATE NULL DEFAULT NULL,
	`LASTACT` DATETIME NULL DEFAULT NULL,
	`LASTPING` DATETIME NULL DEFAULT NULL,
	`WORKSTATUS` INT(2) NULL DEFAULT '0',
	`RXTRAF` VARCHAR(15) NULL DEFAULT NULL,
	`TXTRAF` VARCHAR(15) NULL DEFAULT NULL,
	`DATEINNET` DATE NULL DEFAULT NULL,
	`LASTLOGONTIME` DATETIME NULL DEFAULT NULL,
	`LASTLOGOFFTIME` DATETIME NULL DEFAULT NULL,
	`LOGONHISIP` BIGINT(20) NULL DEFAULT NULL,
	`AGENT_VER` VARCHAR(11) NULL DEFAULT NULL,
	`AGENT_LASTVISIT` DATETIME NULL DEFAULT NULL,
	`AGENT_DATA` MEDIUMTEXT NULL,
	`USERLANG` VARCHAR(11) NULL DEFAULT NULL,
	`ISVIP` INT(1) NULL DEFAULT NULL,
	`LASTVISIT` DATETIME NULL DEFAULT NULL,
	`LOGONIP` DOUBLE NULL DEFAULT NULL,
	`DATEAKCIYA` DATE NULL DEFAULT NULL,
	`METR` INT(3) UNSIGNED NULL DEFAULT NULL,
	`DATEADD` DATETIME NULL DEFAULT NULL,
	`BILLCODE` INT(3) NULL DEFAULT NULL,
	`NOTINBILLING` INT(1) NULL DEFAULT NULL,
	`DATEPAID` DATE NULL DEFAULT NULL,
	`TARIF_DATESTART` DATE NULL DEFAULT NULL,
	`ACC_F` INT(11) NULL DEFAULT NULL,
	`PARENTCODE` INT(11) NULL DEFAULT NULL,
	`NOTSMS` INT(1) NULL DEFAULT NULL,
	`DISABLE` INT(1) NULL DEFAULT '0',
	`DATECHANGESTATUS` DATE NULL DEFAULT NULL,
	`LS` VARCHAR(255) NULL DEFAULT '',
	`TYPER_UPDACT` INT(3) NULL DEFAULT '0',
	PRIMARY KEY (`CODE`),
	UNIQUE INDEX `BILLKEY` (`BILLCODE`, `CODETI`),
	INDEX `CODETI` (`CODETI`),
	INDEX `GROUPN` (`GROUPN`),
	INDEX `HOUSEC` (`HOUSEC`),
	INDEX `FIO` (`FIO`),
	INDEX `LASTACT` (`LASTACT`),
	INDEX `LASTPING` (`LASTPING`),
	INDEX `LASTVISIT` (`LASTVISIT`),
	INDEX `DATEINNET` (`DATEINNET`),
	INDEX `WORKSTATUS` (`WORKSTATUS`),
	INDEX `ISREG` (`ISREG`),
	INDEX `LOGNAME` (`LOGNAME`),
	INDEX `DATEPLUS` (`DATEPLUS`),
	INDEX `BALANS` (`BALANS`),
	INDEX `BILLCODE` (`BILLCODE`),
	INDEX `NOTINBILLING` (`NOTINBILLING`),
	INDEX `ACC_F` (`ACC_F`),
	INDEX `PARENTCODE` (`PARENTCODE`),
	INDEX `DISABLE` (`DISABLE`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=FIXED
AUTO_INCREMENT=2147483648



Как я сейчас узнал, несмотря на срабатывание on duplicate key, счетчик на таблице все равно увеличивается.
Вчера он переполнился и скрипт работать перестал.
Заменять int на bigint я бы не хотел — система большая и неизвестно, где это вылезет боком.
Я бы хотел просто "уплотнить" таблицу, перенумеровав ее заново (в этой таблице около 10к записей) и заодно обновив FK в зависимых таблицах.

Вопроса у меня два.

1. Есть ли готовый скрипт или утилита для такого "уплотнения", который бы сам умел находить зависимости?

2. Можно ли это предотвратить в дальнейшем, чтобы счетчик не увеличивался, когда строка не добавляется?
...
Рейтинг: 0 / 0
27.02.2018, 09:50
    #39607631
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
1. Если и есть, то работать она сможет только в случае, если имеется FK.
2. Нет.
...
Рейтинг: 0 / 0
27.02.2018, 10:52
    #39607689
paver
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Alibek B.,
Тут похожая проблема обсуждается
https://habrahabr.ru/post/156489/
Пишут, что ODKU увеличит Auto Incriment поле на единицу для InnoDB, для MyIsam все работает правильно.
Советуют также для автоинкремента использовать UNSIGNED
Может будет полезно
...
Рейтинг: 0 / 0
27.02.2018, 10:55
    #39607692
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Ок.
Тогда не поможете составить скрипт?
Список зависимостей я составил вручную и сохранил в таблицу:
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE `remap_base_ref` (
	`table` VARCHAR(200) NOT NULL, --имя таблицы FK
	`column` VARCHAR(200) NOT NULL, --имя столбца FK
	`conditions` VARCHAR(2000) NULL, --дополнительные ограничения WHERE
	PRIMARY KEY (`table`, `column`)
)


Таблица соответствия идентификаторов (старый-новый) у меня подготовлена в таблице:
Код: sql
1.
2.
3.
4.
CREATE TABLE `remap_base_ids` (
	`oid` INT(11) NOT NULL,
	`nid` INT(11) NOT NULL
)


Как мне пройтись по remap_base_ref, сгенерировав SQL, в котором указанные столбцы будут обновлены в соответствии с таблицей соответствия?
Можно ли это сделать простым SQL-скриптом? Или нужно делать процедуру?
...
Рейтинг: 0 / 0
27.02.2018, 10:57
    #39607694
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
paverПишут, что ODKU увеличит Auto Incriment поле на единицу для InnoDB, для MyIsam все работает правильно.
У меня с MyISAM печальный опыт повреждения данных.
Буду иметь ввиду, но хотелось бы найти другой способ.

paverСоветуют также для автоинкремента использовать UNSIGNED
Это несколько отсрочит проблему, но не решит ее.
Правильнее будет написать процедуру "упаковки" и запускать ее раз в год.
...
Рейтинг: 0 / 0
27.02.2018, 11:00
    #39607699
paver
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Alibek B. но хотелось бы найти другой способ.
Там в каментах варианты предлагаются, может что и подойдет
...
Рейтинг: 0 / 0
27.02.2018, 11:55
    #39607750
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Подскажите, что не так в запросе?
Ошибочные блоки закомментированы.
Код: sql
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.
BEGIN

declare DONE int(1) default 0;
declare CMAX int;
declare TBL varchar(80);
declare FLD varchar(80);
declare COND varchar(200);
declare Q varchar(2000);
declare CUR cursor for select `table`, `column`, `conditions` from `remap_base_ref`;

declare continue handler for sqlstate '02000' set DONE = 1;

truncate `remap_base_ids`;
alter table `remap_base_ids` AUTO_INCREMENT=1;
insert into `remap_base_ids` (`oid`) select `CODE` from `tbl_base` order by 1;

open CUR;
repeat
	fetch CUR into TBL, FLD, COND;
	if not DONE then
		set Q = concat('update `', TBL, '` B join `remap_base_ids` R on (R.`oid` = B.`', FLD, '`');
		set Q = concat(Q, ifnull(concat(' and ',COND),''), ')');
		set Q = concat(Q, ' set B.`', FLD, '` = R.`nid`;');
/*		prepare ST from Q;
		execute ST;
		deallocate prepare ST;*/
	end if;
until DONE end repeat;
close CUR;

update `tbl_base` B join `remap_base_ids` R on (R.`oid` = B.`CODE`) set B.`CODE` = R.`nid`;
select max(`nid`) into CMAX from `remap_base_ids`;
/*alter table `tbl_base` AUTO_INCREMENT=CMAX;*/

END


Как правильно выполнять динамический SQL в процедурах?
И почему я не могу использовать в alter table переменную?
...
Рейтинг: 0 / 0
27.02.2018, 12:22
    #39607774
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Alibek B.Как правильно выполнять динамический SQL в процедурах?
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html

Alibek B.почему я не могу использовать в alter table переменную?
В первом случае - надо смотреть, что получилось в переменной Q.
Во втором случае - присваиваемое значение в предложении AUTO_INCREMENT является литералом, а не параметром.
...
Рейтинг: 0 / 0
27.02.2018, 14:25
    #39607884
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
AkinaВ первом случае - надо смотреть, что получилось в переменной Q.
Так дело даже до компиляции не доходит.
Как только я задаю prepare с комментарием, процедура перестает сохраняться.
AkinaВо втором случае - присваиваемое значение в предложении AUTO_INCREMENT является литералом, а не параметром.
То есть нужно использовать динамический SQL? Или это можно как-то обойти?
...
Рейтинг: 0 / 0
27.02.2018, 14:28
    #39607891
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Сейчас специально проверил.
Пишу:
Код: sql
1.
prepare ST from '';


Процедура успешно сохраняется.
Пишу:
Код: sql
1.
prepare ST from Q;


Получаю ошибку:
SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'Q;
(хотя в Q валидный SQL, который сам по себе выполняется)
...
Рейтинг: 0 / 0
27.02.2018, 14:42
    #39607899
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Странно, а так работает:
Код: sql
1.
2.
set @SQL = Q;
prepare ST from @SQL;


Не подскажите, в чем разница?
И почему такое все же не работает:
Код: sql
1.
2.
select max(`nid`) into @MAX from `remap_base_ids`;
alter table `tbl_base` AUTO_INCREMENT=@MAX;
...
Рейтинг: 0 / 0
27.02.2018, 14:46
    #39607904
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Ну написано же, ё моё:
https://dev.mysql.com/doc/refman/5.7/en/prepare.html preparable_stmt is either a string literal or a user variable that contains the text of the SQL statement. Два варианта:
- string literal
- user variable
Всё! третьего не дано! локальные переменные - не катят.
...
Рейтинг: 0 / 0
27.02.2018, 14:48
    #39607905
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Финальная версия скрипта:
Код: sql
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.
BEGIN

declare DONE int(1) default 0;
declare TBL varchar(80);
declare FLD varchar(80);
declare COND varchar(200);
declare Q varchar(2000);
declare CUR cursor for select `table`, `column`, `conditions` from `remap_base_ref`;

declare continue handler for sqlstate '02000' set DONE = 1;

truncate `remap_base_ids`;
alter table `remap_base_ids` AUTO_INCREMENT=1;
insert into `remap_base_ids` (`oid`) select `CODE` from `tbl_base` order by 1;

open CUR;
repeat
	fetch CUR into TBL, FLD, COND;
	if not DONE then
		set Q = 'update `$TBL` B join `remap_base_ids` R on (R.`oid` = B.`$FLD` and $COND) set B.`$FLD` = R.`nid`;';
		set Q = replace(Q, '$TBL', TBL);
		set Q = replace(Q, '$FLD', FLD);
		set Q = replace(Q, ' and $COND', ifnull(concat(' and ', COND), ''));
		set @SQL = Q;
		prepare ST from @SQL;
		execute ST;
		deallocate prepare ST;
	end if;
until DONE end repeat;
close CUR;

update `tbl_base` B join `remap_base_ids` R on (R.`oid` = B.`CODE`) set B.`CODE` = R.`nid`;
select max(`nid`) into @MAX from `remap_base_ids`;
set @SQL = concat('alter table `tbl_base` AUTO_INCREMENT=', ifnull(@MAX,0)+1);
prepare ST from @SQL;
execute ST;
deallocate prepare ST;

END


Не подскажите, есть что исправить?
...
Рейтинг: 0 / 0
27.02.2018, 16:20
    #39607972
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Alibek B.
Код: sql
1.
2.
select max(`nid`) into @MAX from `remap_base_ids`;
set @SQL = concat('alter table `tbl_base` AUTO_INCREMENT=', ifnull(@MAX,0)+1);


А чего не сразу
Код: sql
1.
SELECT CONCAT('ALTER TABLE `tbl_base` AUTO_INCREMENT=', ifnull(MAX(`nid`),0)+1) INTO @SQL FROM `remap_base_ids`;

?
Alibek B.есть что исправить?
Ну разве что вынести
Код: sql
1.
set Q = 'update `$TBL` B join `remap_base_ids` R on (R.`oid` = B.`$FLD` and $COND) set B.`$FLD` = R.`nid`;';

за цикл, а REPLACE() делать в другую переменную...
...
Рейтинг: 0 / 0
28.02.2018, 11:53
    #39608383
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Вообщем все прошло успешно, никаких ошибок и сбоев не выявилось.
Единственное, что я сделал еще — это добавил в первоначальный скрипт (который выполняет множество insert с ODKU) в конце alter table tbl_base AUTO_INCREMENT=<select max(CODE)+1 from tbl_base> — тогда не потребуется раз в год повторно делать "упаковку".
...
Рейтинг: 0 / 0
09.03.2018, 08:33
    #39612424
Amin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Я так понимаю, вы подтаскиваете абонентов из стороннего биллинга, который юзерсайдом напрямую не поддерживается, верно ?

С новых версий у них есть свой API, возможно, имеет смысл его задействовать, а не мучить базу этой прекрасной учётной системы столь злым скриптом, переполняющим счётчик.

http://wiki.userside.eu/API
http://wiki.userside.eu/ERP_"USERSIDE"

Хотя хак в автоинкрементом тоже ОК, главное, про бэкапы не забывать =)
...
Рейтинг: 0 / 0
09.03.2018, 11:29
    #39612467
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
API построчный (за раз работает с одной записью) и тормозной. Да и неудобный.
...
Рейтинг: 0 / 0
09.03.2018, 11:33
    #39612469
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Alibek B.alter table tbl_base AUTO_INCREMENT=<select max(CODE)+1 from tbl_base>Можно упростить:
Код: sql
1.
alter table tbl_base AUTO_INCREMENT=1
...
Рейтинг: 0 / 0
09.03.2018, 11:54
    #39612483
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
А дублей не будет? В таблице ведь уже есть записи.
...
Рейтинг: 0 / 0
09.03.2018, 12:01
    #39612487
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Alibek B.А дублей не будет? В таблице ведь уже есть записи.Не будет.
https://dev.mysql.com/doc/refman/5.7/en/alter-table.html To reset the current auto-increment value:
Код: sql
1.
ALTER TABLE t1 AUTO_INCREMENT = 13;


You cannot reset the counter to a value less than or equal to the value that is currently in use. For both InnoDB and MyISAM, if the value is less than or equal to the maximum value currently in the AUTO_INCREMENT column, the value is reset to the current maximum AUTO_INCREMENT column value plus one .
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
27.10.2020, 22:28
    #40012388
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
У меня в процедуре имеется цикл, внутри которого генерируется и выполняется динамический SQL:
Код: sql
1.
2.
3.
4.
		SET @SQL = Q;
		PREPARE ST FROM @SQL;
		EXECUTE ST;
		DEALLOCATE PREPARE ST;



Хочу перед запуском процедуры убедится, что все генерируется правильно.
Вызов SQL комментирую, а вместо него пишу:
Код: sql
1.
SELECT Q AS 'SQL';



В результате получаю несколько десятков однострочных resultset.
Для читабельности хотелось бы вместо них получить один многострочный resultset.
Это возможно сделать?
...
Рейтинг: 0 / 0
27.10.2020, 23:15
    #40012401
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
-- ...
SET @sql := '';
cycle:
    -- ...
    SET @sql := CONCAT(@sql, q);
    -- ...
end_cycle;
SELECT @sql;
-- ...
...
Рейтинг: 0 / 0
27.10.2020, 23:41
    #40012411
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Alibek B.
В результате получаю несколько десятков однострочных resultset.
Для читабельности хотелось бы вместо них получить один многострочный resultset.
Пишите в таблицу:
Код: sql
1.
INSERT INTO debug_table SELECT Q AS 'SQL';


А потом из нее прочитаете.
...
Рейтинг: 0 / 0
28.10.2020, 08:40
    #40012460
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Akina , это же не многострочный resultset.

miksoft
Пишите в таблицу:

Так и сделал.
Просто думал, что может быть в MySQL есть что-то вроде табличной переменной или возвращаемого курсора.
...
Рейтинг: 0 / 0
28.10.2020, 08:51
    #40012463
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переполнился счетчик
Alibek B.
это же не многострочный resultset.
?? не понял фразы.
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Переполнился счетчик / 25 сообщений из 27, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]