Transactions: How to make them work with FireDAC and mySQL? [duplicate] - mysql

I'm using a MySQL DB for my site, which is hosted on a Linux shared server.
I wrote a test script which I run using 'mysql' to test if transactions are working ok. Running the script, I do not get any error, but the result of executing the scripts is as if transaction is not enabled.
I also made sure to grant ALL privileges to the admin MySQL user which runs the script.
In order to double check, I tried the same test script on PostgreSQL, and there - the result of the script indicated that transaction does work. So it's definitely something which is specific to MySQL.
The script runs on a simple table which I created as follows:
create table a ( id serial primary key);
Following is the test script:
delete from a;
set autocommit = 0;
start transaction;
insert into a(id) values(1);
rollback work;
select count(*) from a;
So the script makes sure the table is empty, Then it starts a transaction, insert a row and rollback the insert. As the "insert" is rolled back, the "select" should indicate that table contains 0 rows.
Running this on PostgreSQL:
$ psql db admin < test1
DELETE 0
START TRANSACTION
INSERT 0 1
ROLLBACK
count
-------
0
This is the expected behavior, 0 rows in the table as the insert was rolled back.
Running the same on my MySQL DB:
$ mysql db -u admin < test1
count(*)
1
Having 1 row following the rollback indicate that the "insert" was not rolled back, just as in non-transaction mode.
As mentioned, admin is granted with ALL privileges to the DB.
Anything I've missed?

Probably the table is created with the MyISAM storage engine as default.
MyISAM storage engine doesnt support transactions.
Create table
CREATE TABLE a ( id SERIAL PRIMARY KEY) ENGINE = MYISAM;
Query
DELETE FROM a;
SET autocommit = 0;
START TRANSACTION;
INSERT INTO a(id) VALUES(1);
ROLLBACK WORK;
SELECT COUNT(*) FROM a;
Result
count(*)
1
Making the table InnoDB
Query
ALTER TABLE a ENGINE=INNODB;
Query
DELETE FROM a;
SET autocommit = 0;
START TRANSACTION;
INSERT INTO a(id) VALUES(1);
ROLLBACK WORK;
SELECT COUNT(*) FROM a;
Result
count(*)
----------
0

Related

MySQL SELECT FOR UPDATE is locking whole table

MySQL Version 5.7.16
Process 1:
START TRANSACTION;
SELECT * from statistic_activity WHERE activity_id = 1 FOR UPDATE;
Process 2:
START TRANSACTION;
INSERT INTO `statistic_activity` (`activity_id`) values (2678597);
If Process 1 SELECT statement returns results, Process 2 is not blocked (as you will expect)
But If Process 1 returns empty set (no rows exists with activity_id = 1) then whole table is locked and all INSERTS are blocked until Process 1 transaction ends.
Is this expected behavior ?

Is it possible to create a Lost Update with MySQL Workbench

I want to create a Lost Update with MySQL Workbench. Therefore, I have 2 connections to my database and 2 transactions. I also changed the transaction isolation level to read uncommitted but transaction A uses the current data when the update statement starts. It never uses the data from the first select statement and with select ... for update the transaction b is blocked.
Transaction A (starts first):
Start transaction;
SELECT * FROM table;
Select sleep(10); -- <- Transaction B executes in this 10 seconds
UPDATE table SET Number = Number + 10 WHERE FirstName = "Name1";
COMMIT;
Transaction B:
Start transaction;
UPDATE table SET Number = Number - 5 WHERE FirstName = "Name1";
COMMIT;
Is it possible to create this failure with MySQL Workbench. What´s wrong with my code?
Thanks for your help
The update in A work with data after the sleep is executed. Select before does nothing in the transaction.

Transactions not working for my MySQL DB

I'm using a MySQL DB for my site, which is hosted on a Linux shared server.
I wrote a test script which I run using 'mysql' to test if transactions are working ok. Running the script, I do not get any error, but the result of executing the scripts is as if transaction is not enabled.
I also made sure to grant ALL privileges to the admin MySQL user which runs the script.
In order to double check, I tried the same test script on PostgreSQL, and there - the result of the script indicated that transaction does work. So it's definitely something which is specific to MySQL.
The script runs on a simple table which I created as follows:
create table a ( id serial primary key);
Following is the test script:
delete from a;
set autocommit = 0;
start transaction;
insert into a(id) values(1);
rollback work;
select count(*) from a;
So the script makes sure the table is empty, Then it starts a transaction, insert a row and rollback the insert. As the "insert" is rolled back, the "select" should indicate that table contains 0 rows.
Running this on PostgreSQL:
$ psql db admin < test1
DELETE 0
START TRANSACTION
INSERT 0 1
ROLLBACK
count
-------
0
This is the expected behavior, 0 rows in the table as the insert was rolled back.
Running the same on my MySQL DB:
$ mysql db -u admin < test1
count(*)
1
Having 1 row following the rollback indicate that the "insert" was not rolled back, just as in non-transaction mode.
As mentioned, admin is granted with ALL privileges to the DB.
Anything I've missed?
Probably the table is created with the MyISAM storage engine as default.
MyISAM storage engine doesnt support transactions.
Create table
CREATE TABLE a ( id SERIAL PRIMARY KEY) ENGINE = MYISAM;
Query
DELETE FROM a;
SET autocommit = 0;
START TRANSACTION;
INSERT INTO a(id) VALUES(1);
ROLLBACK WORK;
SELECT COUNT(*) FROM a;
Result
count(*)
1
Making the table InnoDB
Query
ALTER TABLE a ENGINE=INNODB;
Query
DELETE FROM a;
SET autocommit = 0;
START TRANSACTION;
INSERT INTO a(id) VALUES(1);
ROLLBACK WORK;
SELECT COUNT(*) FROM a;
Result
count(*)
----------
0

Does the MySQL workbench show uncommitted changes?

Why does the MySQL workbench show uncommitted changes?
-- create a new empty table
DROP TABLE IF EXISTS X;
CREATE TABLE X (val varchar(10));
-- disable autocommit
SET AUTOCOMMIT = 0;
-- insert a row without committing
INSERT INTO X (val) VALUES ('text');
At this point
SELECT ##autocommit, ##tx_isolation;
returns
| 0 | REPEATABLE-READ |
However, a query shows the value which has not yet been committed:
SELECT * FROM X;
| text |
Why does MySQL return a result set with uncommitted data?
If I roll back the transaction using
ROLLBACK;
then MySQL returns an empty table when querying X. (That confirms that the transaction hasn't been committed automatically at some point of time.)
The reason is that I am always in the same transaction (regardless the window tab).

MyISAM Selects locks inserts inside procedure only

We have a large MyISAM table to which rows get inserted to the bottom of the table only.
While doing some benchmarks, i realized that selects do not (always) lock other inserts to that same table. However, when the inserts are coming from a stored procedure/function they will by locked by the select.
Why is that?
To demonstrate this behavior:
CREATE TABLE Foo (
ID INT NOT NULL AUTO_INCREMENT,
Bar VARCHAR(200),
PRIMARY KEY(ID)) ENGINE=MyISAM;
--INSERT into Foo 10M rows
DELIMITER $$
DROP PROCEDURE IF EXISTS InsertProc$$
CREATE PROCEDURE InsertProc(IN vBar VARCHAR(255))
BEGIN
INSERT Foo(Bar) VALUES (vBar);
END$$
DELIMITER ;
Run the following query:
SELECT Count(*) FROM Foo WHERE INSTR(Bar, 'abcdefg') > 0;
While that Select is running, open a new connection and run the following insert query:
INSERT Foo(Bar) VALUES ('xyz1234');
That Insert will run and return right away, However if i run the following query:
CALL InsertProc('xyz1234');
Now the query locks and waits for the select to complete.
MySql Version: 5.0.51 running on Window Server 2K3
Thank you.
-- UPDATE
Here is the profile output:
Insert Direct:
(initialization) 0.0000432
checking permissions 0.0000074
Opening tables 0.0000077
System lock 0.0000032
Table lock 0.0000025
init 0.000021
update 0.0002365
end 0.0000382
query end 0.000002
freeing items 0.0000057
closing tables 0.0000022
logging slow query 0.0000005
Insert via Procedure:
(initialization) 0.0000285
Opening tables 0.0004325
System lock 0.0000022
Table lock 0.0002957
checking permissions 0.0000047
Opening tables 0.000004
System lock 0.0000017
Table lock 3.2365122
init 0.0000422
update 0.000251
end 0.0000025
query end 0.000003
closing tables 0.00004
query end 0.0000074
freeing items 0.0000074
logging slow query 0.000001
cleaning up 0.5790915
Why does the procedure open and "Table lock" twice?
This issue was submitted as a bug:
http://bugs.mysql.com/bug.php?id=58689
MyIASM for any particular reason? InnoDB tables usually have much better locking characteristics.
Speculation: perhaps the locking/mutex handling on the AUTO_INCREMENT field on MyISAM tables is stricter when stored procedures are used.
To rule it out, could you set up a test where ID wasn't an AUTO_INCREMENT field?
Have you given INSERT DELAYED a try if you application might allow for it?