Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá,
Possuo alugado um servidor dedicado com 4 cores 1.6Ghz, 16Gb de RAM, 500GB HD e link de dicado de 100Mb. Nesse servidor tenho apenas um sistema em php em funcionamento, ultimamente mesmo que não haja nenhum internauta navegando o MySql está consumindo demasiadamente a CPU, já revirei na net sobre esse assunto e as dicas são sempre as mesmas, configurei o my.cnf, criei indices no banco de dados, mas até agora nada... Segue o arquivo de configuração my.cnf
[mysqld]
key_buffer=312M
join_buffer=16M
max_join_size=16M
thread_concurrency=4
table_cache=2048M
open_files_limit=2000
query_cache_limit=128M
query_cache_type=2
query_cache_size=128M
long_query_time=10
slow_query_log=1
key_buffer_size=256M
slow_query_log_file="/var/log/mysql-slow.log"
max_allowed_packet=256M
sort_buffer_size=256M
max_connections=500
thread_cache_size=24
read_buffer_size=8M
read_rnd_buffer_size=64M
myisam_sort_buffer_size=256M
innodb_flush_log_at_trx_commit=2
innodb_buffer_pool_size=256M
innodb_additional_mem_pool_size=60M
wait_timeout=15
thread_cache=32
max_connections=1000
Essa é a situação atual do servidor com 20 pessoas acessando o site:
Cpu(s): 29.2%us, 3.8%sy, 0.0%ni, 66.4%id, 0.5%wa, 0.0%hi, 0.1%si, 0.0%st
Mem: 16608840k total, 4851588k used, 11757252k free, 255292k buffers
Swap: 5636088k total, 0k used, 5636088k free, 4089260k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27451 mysql 15 0 794m 186m 6884 S 170.7 1.2 247:29.16 mysqld
20818 nobody 15 0 9852 3184 1516 S 0.7 0.0 0:00.06 httpd
22047 nobody 15 0 9852 3184 1516 S 0.7 0.0 0:00.06 httpd
7051 nobody 15 0 9852 3212 1528 S 0.3 0.0 0:00.15 httpd
19447 nobody 15 0 9852 3184 1516 S 0.3 0.0 0:00.07 httpd
20573 nobody 15 0 9852 3204 1536 S 0.3 0.0 0:00.06 httpd
20978 nobody 15 0 9852 3176 1512 S 0.3 0.0 0:00.06 httpd
22045 nobody 15 0 9852 3184 1516 S 0.3 0.0 0:00.05 httpd
Peço a ajuda de todos.
Olá Prog, obrigado pela resposta,
Tem um job sim, que inicialmente funcionava normal, no arquivo mysql-slow.log que criei para registrar as consultas mais lentas a chamada ao job é a mais presente:
SET timestamp=1357754847;
call cron_tempo();
SET timestamp=1357754848;
call cron_tempo();
SET timestamp=1357754849;
call cron_tempo();
OBS: Existem mais umas 500 linha como essas
Trata-se de um leilão de centavos
Não sei se tem a ver com a conexão persistente ou não, porque
nesse momento, sem nenhum usuario online o mysql está consumindo 90%. Mas não existe conexões persistentes no código.
Esse é o resultado do SHOW FULL PROCESSLIST;
mysql> show full processlist;
+---------+-----------+-----------+-----------+----------------+------+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+---------+-----------+-----------+-----------+----------------+------+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2595914 | DELAYED | localhost | eximstats | Delayed insert | 230 | Waiting for INSERT | |
| 2602572 | DELAYED | localhost | eximstats | Delayed insert | 146 | Waiting for INSERT | |
| 2602573 | DELAYED | localhost | eximstats | Delayed insert | 146 | Waiting for INSERT | |
| 2611233 | root | localhost | NULL | Query | 0 | NULL | show full processlist |
| 2612849 | lance_adm | localhost | lance_bd | Sleep | 0 | | NULL |
| 2612851 | lance | localhost | lance_bd | Query | 0 | Copying to tmp table | CREATE TEMPORARY TABLE t_robos
SELECT auctionID, productID, auc_due_time, auc_plus_time, auc_due_price+auc_plus_price AS prox_valor, proximo_robo(ultUserId) AS prox_robo
from c_cron_tempo where auc_due_time < 2 |
+---------+-----------+-----------+-----------+----------------+------+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
6 rows in set (0.00 sec)
O código do JOB é esse:
BEGIN
DECLARE total BIGINT DEFAULT 0;
DECLARE bloquear TINYINT(1) DEFAULT 0;
DECLARE qt_robo INT DEFAULT 0;
SELECT COUNT(*) FROM cron INTO total;
IF total = 0 THEN
INSERT INTO cron (tempo) VALUES (NOW());
SELECT 1, 0 INTO total, bloquear;
ELSE
SELECT NOW()-tempo AS total, bloquear FROM cron INTO total, bloquear;
END IF;
IF total > 0 AND bloquear = 0 THEN
UPDATE cron SET tempo=NOW();
BEGIN
-- contagem regressiva dos leiloes ativos
update auc_due_table adt left join auction a on a.auctionID=adt.auction_id
set adt.auc_due_time=adt.auc_due_time-1
where adt.auc_due_time>0 and a.pause_status=0 and a.auc_status=2;
-- ativar os leiloes futuros que estao no horario de inicio
update auction a set auc_status=2 where pause_status=0 and auc_status=1 and
(TIMEDIFF(DATE_FORMAT(concat(concat(auc_start_date,' '),
auc_start_time),'%Y-%m-%d %T'),DATE_FORMAT(NOW(),'%Y-%m-%d %T'))+0)<0; Insert Into auc_due_table(auction_id,auc_due_time,auc_due_price,auc_limite_total)
SELECT a.auctionID,m.auc_plus_time,m.auc_plus_price,a.max_robot_consec
FROM auction a inner join auction_management m on
a.time_duration=m.auc_manage left join auc_due_table t on a.auctionID=t.auction_id
where t.auc_due_time is null and (a.auc_status=2 or a.auc_status=1) and a.pause_status=0;
-- robo mantendo o preco minimo se exiter mais de 1 robo cadastrado
SELECT COUNT(*) AS tot FROM registration where admin_user_flag='1' and user_delete_flag != 'd' INTO qt_robo;
IF qt_robo > 1 THEN
CREATE TEMPORARY TABLE t_robos
SELECT auctionID, productID, auc_due_time, auc_plus_time, auc_due_price+auc_plus_price AS prox_valor, proximo_robo(ultUserId) AS prox_robo
from c_cron_tempo where auc_due_time < 2;
-- dar lance
Insert into bid_account (user_id,bidpack_buy_date,bid_count,auction_id,product_id,bid_flag,bidding_price,bidding_type,bidding_time)
SELECT prox_robo,NOW(),'1',auctionID,productID,'d',prox_valor,'s',auc_due_time FROM t_robos;
-- retornar o tempo e aumentar o preco
UPDATE auc_due_table INNER JOIN t_robos SET auc_limite_atual=auc_limite_atual+1, auc_due_table.auc_due_time=t_robos.auc_plus_time, auc_due_table.auc_due_price=t_robos.prox_valor
WHERE auc_due_table.auction_id = t_robos.auctionID;
DROP TABLE t_robos;
-- listar os leiloes em aberto que nao possuem lance
CREATE TEMPORARY TABLE t_robos
SELECT a.auctionID, a.productID, t.auc_due_time, m.auc_plus_time, t.auc_due_price+m.auc_plus_price AS prox_valor, m.auc_plus_price, proximo_robo(0) as prox_robo
FROM auction a inner join auction_management m on a.time_duration=m.auc_manage left join auc_due_table t on a.auctionID=t.auction_id
left join bid_account l on a.auctionID = l.auction_id
where a.auc_status=2 and a.pause_status=0 and l.auction_id is null and t.auc_due_time < 3;
-- dar lance
Insert into bid_account (user_id,bidpack_buy_date,bid_count,auction_id,product_id,bid_flag,bidding_price,bidding_type,bidding_time)
SELECT prox_robo,NOW(),'1',auctionID,productID,'d',prox_valor,'s',auc_due_time FROM t_robos;
-- retornar o tempo e aumentar o preco
UPDATE auc_due_table INNER JOIN t_robos SET auc_due_table.auc_due_time=t_robos.auc_plus_time, auc_due_table.auc_due_price=t_robos.prox_valor
WHERE auc_due_table.auction_id = t_robos.auctionID;
DROP TABLE t_robos;
END IF;
-- fechar os leiloes q esgotaram o tempo :: avisar ganhador
update auc_due_table adt left join auction a on a.auctionID=adt.auction_id left join
(select g.auction_id, d.user_id from
(select max(id) as id, auction_id from bid_account
where bid_flag = 'd' and bidding_type = 's'
group by auction_id) g inner join
bid_account d on g.id=d.id) b on a.auctionID=b.auction_id
set a.auc_status=3, a.auc_final_price = adt.auc_due_price,
a.auc_final_end_date=NOW(), a.buy_user = COALESCE(b.user_id,0)
where adt.auc_due_time=0 and a.pause_status=0 and a.auc_status=2;
-- cadastrar a opcao de pagamento dos leiloes q venceram
Insert into won_auctions (auction_id,userid,won_date)
Select a.auctionID,buy_user,NOW() from auction a left join
won_auctions w on a.auctionID=w.auction_id
where w.auction_id is null and auc_status=3 and situacao = 0;
COMMIT;
END;
SELECT true AS resultado;
ELSE
SELECT false AS resultado;
END IF;
END
Só complementando, instalei uma ferramenta chamada mytop. Ela sempre me retorna algo parecido com isso:
Queries: 150.0 qps: 0 Slow: 0.0 Se/In/Up/De(%): 00/00/00/00
qps now: 0 Slow qps: 0.0 Threads: 3 ( 2/ 29) 00/00/00/00
Key Efficiency: 100.0% Bps in/out: 0.1/ 15.6 Now in/out: 8.4/ 1.8k
Id User Host/IP DB Time Cmd Query or State
-- ---- ------- -- ---- --- ----------
2686119 root localhost 0 Query show full processlist
2713290 lance_adm localhost lance_bd 0 Sleep
2713291 lance localhost lance_bd 0 Query CREATE TEMPORARY TABLE t_robos SELECT auctionID, productID, auc_due_time, auc_plus_time, auc_due_price+au
2713319 lance_adm localhost lance_bd 0 Sleep
2710573 DELAYED localhost eximstats 40 Delaye Waiting for INSERTEsse JOB roda a cada segundo? Como o sistema fica com o JOB desligado?
Achei o JOB com muita coisa, não que isto não seja necessário, mas me parece que ele precisa ser otimizado e ver se alguns desses processamentos não podem ser substituídos por outros processos fora do banco de dados.
Quanto ao resultado do mytop, é justamente uma das atividades que ocorre dentro do JOB, neste caso, a criação de uma tabela temporária baseada no SELECT abaixo:
SELECT a.auctionID, a.productID, t.auc_due_time, m.auc_plus_time, t.auc_due_price+m.auc_plus_price AS prox_valor, m.auc_plus_price, proximo_robo(0) as prox_robo
FROM auction a inner join auction_management m on a.time_duration=m.auc_manage left join auc_due_table t on a.auctionID=t.auction_id
left join bid_account l on a.auctionID = l.auction_id
where a.auc_status=2 and a.pause_status=0 and l.auction_id is null and t.auc_due_time < 3;
No inicio você disse que o JOB funcionava bem, porém, conforme o banco de dados vai crescendo, algumas consultas que eram velozes no inicio, quando haviam poucos dados, ficaram mais lentas...
Algumas opções:
- rever algumas regras de negócio e processamentos;
- criar mais alguns indices;
Olá meu caro,
Cê me acredita que ainda estou sofrendo com esse server?
eu apaguei a aplicação e o banco de dados e acredite... o mysql continua consumindo muita CPU sozinho.
Ou seja, não era só a aplicação, ainda existe algo, mas o que?
Vocês poderiam me da uma direção do que pode ser esse gargalo?
Agradeço a ajuda.
O show processlist; do mysql ainda mostra que esta executando alguma coisa?
Tente reiniciar o serviço do banco de dados, geralmente service mysqld restart (depende da distribuição) da conta do recado.
Estava reavaliando seu arquivo de configuração:
[mysqld]key_buffer=312M join_buffer=16M max_join_size=16M thread_concurrency=4 table_cache=2048M open_files_limit=2000 query_cache_limit=128M query_cache_type=2 query_cache_size=128M long_query_time=10 slow_query_log=1 key_buffer_size=256M slow_query_log_file="/var/log/mysql-slow.log" max_allowed_packet=256M sort_buffer_size=256M max_connections=500 thread_cache_size=24 read_buffer_size=8M read_rnd_buffer_size=64M myisam_sort_buffer_size=256M innodb_flush_log_at_trx_commit=2 innodb_buffer_pool_size=256M innodb_additional_mem_pool_size=60M wait_timeout=15 thread_cache=32 max_connections=1000
Percebi que algumas chaves estão repetidas, você alterou este arquivo na tentativa de melhorar o problema? Alguns valores me parecem excessivamente altos, usou algum tutorial como referência?
Aguardamos retorno.
Não há jobs configurados?
Sua base de dados tem que tamanho em MB/GB? E quantos registros?
De que se trata a sua aplicação? É uma aplicação desenvolvida por terceiros?
Usa conexões persistentes ou você quem faz o controle?
Acesse o MySQL e execute show processlist; (mostre o resultado).