Jump to content


DouglasDomi

Member Since 06/02/2011
Offline Last Active 11/07/2011, 16:31
-----

Posts I've Made

In Topic: Problema Com Transactions

09/07/2011, 16:42

Não tenho muita experiência com transações, mas até onde eu sei, é pra acontecer como você está querendo sim. Qualquer operação fora da sua transação que venha a envolver o registro travado será suspensa até que ele seja liberado.


OK LeoB. Obrigado por toda ajuda.

Você nem sabe o quando pesquisei sobre concorrencias em MySQL.

RESOLVIDO =D

In Topic: Problema Com Transactions

09/07/2011, 16:19

O FOR UPDATE vai travar tanto a leitura por outras transações quanto por outros usuários.


ou seja, bloqueia qualquer operação??

veja o codigo

// captura dados do mecanismo que vai forjar o item e o item a ser forjado
			 $ArrayForja = $SqlForja->fetch_array(MYSQLI_ASSOC);
			 
			 // inicia transaction para remover os itens do inventario
			 $this->db->consql->query("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; START TRANSACTION;");
			 $this->db->consql->query("SELECT * FROM inventario WHERE meca_id = ".$this->id." FOR UPDATE;");
			 
			 // cria variavel vazia que vai remover os materiais necessarios para criar o item
			 $QrMateriais = "";		 
			 
			 // verifica se o mecanismo do jogador tem todos os itens da forja no inventario
			 WHILE ($ArrayMateriais = $SqlMateriais->fetch_array(MYSQLI_ASSOC))
			 {
			      // cria query where de filtragem dos itens a serem pesquisados
			      $Where = "WHERE meca_id = ".$this->id." AND item_id = ".$ArrayMateriais['item_id']." AND equipado = 0 ORDER BY nivel LIMIT ".$ArrayMateriais['quantia'].";";
			     			     
			      // cria query que verifica se o mecanismo do jogador tem o material    
			      $Qr = "SELECT id FROM inventario ".$Where;			      
			      
			      // executa query
			      $this->db->consql->query($Qr);
			      
			      // verifica se o foi tirada a quantia necessaria do item se não da rollback
			      IF ($this->db->consql->affected_rows != $ArrayMateriais['quantia'])
			      {	       
				   print "Faltam itens para completar esta forja.";
			 
				   RETURN FALSE;
			      }
			      ELSE
			      {
				   // implementa query para remover material		    
				   $QrMateriais .= "DELETE FROM inventario ".$Where;
			      }
			 }
			 
			  // cria a query para adicionar o item forjado no inventario
			 $Qr = "INSERT INTO inventario(meca_id,item_id,drone_drop,drone_quantia,equipado) VALUES (".$this->id.",".$ArrayForja['item_id'].",0,0,0);";			 

			 // implementa na query de adicionar o item forjado as queries para remover os materias usados na forja
			 $Qr .= $QrMateriais;
			 
			 // executa query
			 $this->db->consql->multi_query($Qr);
			  
			 // executa query para aplicar modificações feitas na transaction
			 $this->db->consql->query("COMMIT");
			 
			 print "Item forjado com sucesso. Já disponivel no inventário.";
				   
			 RETURN TRUE;

veja que quando chamo a função
$this->db->consql->query("SELECT * FROM inventario WHERE meca_id = ".$this->id." FOR UPDATE;");
quero prevenir que ninguem delete,altere ou faça leitura desses registros no banco ate chegar no commit ou rollback do codigo

In Topic: Problema Com Transactions

09/07/2011, 15:55

Isso sempre que um problema como o que você deu de exemplo puder acontecer. Dependendo da situação, travar o registro pode ser desnecessário.



LeoB.

Os DELETEs mesmo em transactions são auto commit, então preciso fazer selects de verificações e depois fazer uma multi_query executando os deletes.
Porem eu não quero que ninguem acesse as linhas de registros enquando eu fazer os selects de verificação na transaction.

Qual a solução? Se eu utilizar FOR UPDATE ele da lock de leitura de outros usuarios também ?, sei que o lock in share mode da lock apenas para remoção e edição de linhas.

In Topic: Problema Com Transactions

07/07/2011, 21:13

Pra mim parece bom. Está dando algum problema?


Não não Leo.

Esta funcionando perfeitamente. testei ate com o timer.

Com isso consigo fazer com que outras pessoas não consigam alterar e nem mecher em nada em que os registros que esta transaction estão usando.

Tenho outro exemplo também que usei..pra remover o dinheiro e depois o item tendo um commit no final...

Entao vou precisar ficar usando os FOR UPDATE para dar lock nas linhas que precisar também..assim outras transactions vao aguardar a transaction atual ser concluida correto?

obrigado pela ajuda.

In Topic: Problema Com Transactions

07/07/2011, 21:02

Entao consegue verifica o codigo abaixo ???

// inicia transaction para investir pontos em habilidades
		    $this->db->consql->query("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; START TRANSACTION;");
		    $this->db->consql->query("SELECT id, cpontos FROM mecanismos WHERE id = ".$this->id." FOR UPDATE;");
		    $this->db->consql->query("SELECT * FROM habilidades WHERE meca_id = ".$this->id." FOR UPDATE;");		    
		    		    
		    // cria a query para remover os pontos a serem investidos
		    $Qr = "UPDATE mecanismos SET cpontos = cpontos - ".$Quantia." WHERE id = ".$this->id." AND cpontos >= ".$Quantia;
				    
		    // executa query     
		    $Sql = $this->db->consql->query($Qr);
	   
		    // verifica se retornou algo na query verificando se existem pontos suficientes
		    IF ($this->db->consql->affected_rows > 0)
		    {
			 // cria a query para investir o ponto na habilidade
			 $Qr = "INSERT INTO habilidades(meca_id,classe_id,valor) VALUES (".$this->id.",".$IdHabilidade.",".$Quantia.") ON DUPLICATE KEY UPDATE valor = valor + ".$Quantia;
		    
			 // executa query     
			 $Sql = $this->db->consql->query($Qr);
		    
			 // verifica se retornou algo na query para inserir os pontos
			 IF ($this->db->consql->affected_rows > 0)
			 {			      
			      // executa query para aplicar modificações feitas na transaction
			      $this->db->consql->query("COMMIT");
			      
			      // atualiza status de combate do mecanismo
			      $this->VerifyStatus();
			      
			      print "Ponto em habilidade investido com sucesso.";
			 }
			 ELSE
			 {
			      // executa query para cancelar a transaction
			      $this->db->consql->query("ROLLBACK");
			 
			      print "Falha ao investir ponto na habilidade.";
			 }
		    }
		    ELSE
		    {
			 // executa query para cancelar a transaction
			 $this->db->consql->query("ROLLBACK");
			 
			 print "Falha ao investir ponto na habilidade.";
		    }

IPB Skin By Virteq