Estou trabalhando no script PHP, que importa o arquivo CSV ( customers.csv
) na tabela MySQL ( customers
).
Antes de inserir o conteúdo do arquivo CSV na tabela mysql, primeiro faço o backup da customers
tabela original .
Estou agrupando todo o processo de importação (incluindo o backup) em uma transação mysql (para considerar casos em que o CSV está corrompido em algum lugar no meio e para garantir que a importação seja atômica).
O problema é que o ROLLBACK parece não funcionar quando eu o chamo logo após a INSERT INTO
instrução: ao verificar o banco de dados via phpMyAdmin, posso ver a tabela recém-criada E AS LINHAS DENTRO ainda presentes após o roollback .
Aqui está o log das operações:
[2015-01-19 14:08:11] DEBUG: "START TRANSACTION" [] []
[2015-01-19 14:08:11] DEBUG: SHOW TABLES LIKE :table_name; [] []
[2015-01-19 14:08:28] DEBUG: CREATE TABLE `customers__20150119_14_08_20` LIKE `customers` [] []
[2015-01-19 14:08:37] DEBUG: INSERT INTO `customers__20150119_14_08_20` SELECT * FROM `customers` [] []
[2015-01-19 14:08:50] DEBUG: "ROLLBACK" [] []
Então, eu me pergunto por que o depsite ROLLBACK
é chamado, a transação não é cancelada. Entendo que CREATE TABLE
não é de natureza transacional e não pode ser revertida. Mas eu estava assumindo que, INSERT INTO
por lidar com a inserção de linhas (sem definir o esquema), SERÁ realmente transacional e, após ROLLBACK, ficarei com a tabela de destino vazia. Por que não é esse o caso?
E aqui está a saída SHOW CREATE TABLE customers
(então minha tabela é InnoDb
):
CREATE TABLE `customers` (
`Code` varchar(32) NOT NULL,
`Name` varchar(128) DEFAULT NULL,
`Price` varchar(128) DEFAULT NULL,
PRIMARY KEY (`Code`),
KEY `Price` (`Price`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
e aqui está a saída para a tabela de desination:
CREATE TABLE `customers__20150119_14_08_20` (
`Code` varchar(32) NOT NULL,
`Name` varchar(128) DEFAULT NULL,
`Price` varchar(128) DEFAULT NULL,
PRIMARY KEY (`Code`),
KEY `Price` (`Price`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
fonte
create table
, entãostart transaction, insert, rollback
?Respostas:
O motivo é que algumas declarações, como
CREATE TABLE
causam um commit implícito. Você pode ler sobre eles na documentação: Declarações que causam um comprometimento implícito .Portanto, a sequência original de instruções:
expandirá para:
A solução seria iniciar a transação (ou uma nova) após a
CREATE TABLE
instrução ou usar uma tabela temporária.fonte
cause an implicit commit
... Então, tive que fazer esse esboço no papel de qualquer maneira :) @RolandoMySQLDBA, agradeço também pela contribuição rápida. Eu li algumas dezenas de respostas no ano passado e elas me ajudaram bastante !!INSERT
, causado pela instrução DDL, também de alguma forma causa um commit após a inserção?Parece que a ordem das instruções está causando o problema.
No meu antigo bloqueio de linha de postagem na transação ACID innodb , nomeei 12 instruções que interrompem uma transação de forma intermitente. No seu caso particular, foi a
CREATE TABLE
afirmação.Depois que você rodava
CREATE TABLE
dentro de um blocoSTART TRANSACTION
...COMMIT/ROLLBACK
, não havia estrutura para reverter.Basta executar o
CREATE TABLE
antesSTART TRANSACTION
e você deve ficar bem.De uma chance !!!
fonte