mysql define variable across all sessions - mysql

I have a table with a few variables (let's say tbl_param). I have to query tbl_param everytime I need to use one of them. I have a case where I need to use those variables inside triggers, so I have to query tbl_param each time those triggers are executed. But what if I am going to use the same variable for every user that connects to the db? It would be logical to set them only once, since it would not change often (only when the variable in question gets updated in tbl_param). I know I can set session variables, but it would not solve the problem as they would be acessible only for the duration of one connection. So when a new connection is made, I would need to query tbl_param again. Can I define, for instance, a new system variable that gets loaded when the server boots up and and that I could update it as tbl_param gets updated? Or is there another alternative?

There are system that can be defined in mysql.cnf (or mysql.ini) file; but this will require you to had file permissions on that file. On my local server (Ubuntu 20.04.2) it is in /etc/mysql/mariadb.conf.d/50-server.cnf. but this would not work on remote server; because we didn't have access to system files (etc).
I had found an alternative to this that would serve the purpose what you had in mind. SET a session variable (wait for it; i know session variables disappears in other sessions); but initialize it value to some value from a table. e.g initialize your session variable always on startup from a table (and update accordingly to table as required).
In case of using a PHP (MIS) to disable mysql triggers
To disable a trigger on some table for some specific record(s). instead of deleting the triggers and inserting the records and then recreating those triggers. just rewrite the trigger with a minor change. it would disable based on this session variable.
Then your MIS would always initialize a session variable to some value fetched from table. and based on this value skip or execute triggers.

Related

MySQL/MariaDB: selected synchronize of tables between instances

I have to synchronize some tables from a MySql-Database to another (different server on different machine).
That transfer should only include special tables and only rows of that tables with a special characteristics (e.g. if a column named transfer is set to 1).
And it should be automatically/transparent, fast and work within short cycles (at least every 20s).
I tried different ways but none of them matched all requirements.
DB-synchronize with Galera works fine but does not exclude tables/rows.
mysqldump is not automatically (must be started) and does not exclude.
Is there no other way for that job beside doing it with some own code that runs permanently?
Those partial sync must be performed with specially created scheme.
Possible realization:
Test does your server instances supports The FEDERATED Storage Engine. By default this is allowed.
Test does destination server may access the data stored on source server using CREATE SERVER.
Create server attached to remote source server and needed remote database. Check that remote data is accessible.
On the destination server create an event procedure which is executed each 20s (and make it disabled firstly). I recommend you to create it in separate service database. In this event procedure execute the queries like
SET #event_start_timestamp = CURRENT_TIMESTAMP;
INSERT localDB.local_table ( {columns} )
SELECT {columns}
FROM serviceDB.federated_table
WHERE must_be_transferred
AND created_at < #event_start_timestamp;
UPDATE serviceDB.federated_table
SET must_be_transferred = FALSE
WHERE must_be_transferred
AND created_at < #event_start_timestamp;
Destination server sends according SELECT query to remote source server. It executes this query and sends the output back. Received rows are inserted. Then destination server sends UPDATE which drops the flag.
Enable Event scheduler.
Enable event procedure.
Ensure that your event procedure is executed fast enough. It must finish its work before the next firing. I.e. execute your code as regular stored procedure and check its execution time. Maybe you'd increase sheduling regularity time.
You may exclude such parallel firings using static flag in some service table created in your service database. If it is set (previous event have not finished its work) then event procedure 'd exit. I recommend you to perform this check anycase.
You must handle the next situation:
destination receives a row;
source updates this row;
destination marks this row as synchronized.
Possible solution.
The flag must_be_transferred should be not boolean but (unsigned tiny)integer, with the next values: 0 - not needed in sync; 1 - needed in sync; 2 - selected for copying, 3 - selected for copying but altered after selection.
Algo:
dest. updates the rows marked with non-zero value and set them to 2;
dest. copies the rows using the condition flag OR 2 (or flag IN (2,3));
dest. clears the flag using the expression flag XOR 2 and above condition.
src. marks altered rows as needed in sync using the expression flag OR 1.

How to set mysql user variable at every new connection in Laravel 5.5?

Background: We rely heavily on views in our app and one of the ways in which we are looking to optimize them is by parameterization. We've got that aspect all figured out, but in order to make it work, I must be able to set a user parameter for the customer (tenant) id. I want to do this at a base level so that it is set for every single connection.
For example the script I want to run is simply:
Set #Param_CustomerId:=1234
where 1234 is the customer id based on the authentication.
Here's the question: Where can I set up code that will get run every time a new MySQL Connection is established?
I think you can run that code in the registerConnectionServices method of a class which would extend the default DatabaseServiceProvider (and use that extended provider instead of the default).

How to pre-set MySQL user variables in config files

MySQL allows usage of User-defined variables How to declare a variable in MySQL?
Is there a way for me to pre-set one such constant, so that it's automatically ready to use in PHP scripts, CLI clients and whatnot? As if every session were automatically started with a
SET #whatever = 2.52;
Create a table, that keeps this value and select from it everywhere, when you need it. That will be a simple subselect in sql queries.

Source and time of update of a column in MySQL

I have a column Quantity in a table Inventory of MySQL which gets updated from multiple sources. I needed to maintain a track in the table on another column called QuantityLog on the last updated time of the Quantity and the source which did it. Something like this should be the content of QuantityLog column (Text type) (only the latest update details is required):
<Log>
<UpdateTime>2015-02-23 12:00:01 PM</UpdateTime>
<Source> Feeder application</Source>
</Log>
I am aware of how to do it using trigger if only the update time is required. However, with the trigger approach is there any other mechanism to get the source and use this too?
Do note pls that I am trying to perform this via triggers only as any other mechanisms of using my application to do this will require me to change in all applications that make this change and I am not inclined to do that.
There is no way MySql can know the "feeder application", unless there is a variable or table filled with that value. If you have this, it is easy to create a trigger that updates this info into the Inventory table on each change of the Quantity field.
However, if your applications use unique mysql users to connect to the database, you can of course use the CURRENT_USER() built in function inside your TRIGGER. Alternatively, CONNECTION_ID() might be helpful when tracking who did what. For example, you can create a new table that logs the connection id of your application. In that table you could write the application name, the PID and other stuff. Of course this would mean to change our application a bit by adding the appropriate insert statement after a connection is established. The overhead should be small, since usually connections are held in pools and do not get re-created all the time.

When a new row in database is added, an external command line program must be invoked

Is it possible for MySQL database to invoke an external exe file when a new row is added to one of the tables in the database?
I need to monitor the changes in the database, so when a relevant change is made, I need to do some batch jobs outside the database.
Chad Birch has a good idea with using MySQL triggers and a user-defined function. You can find out more in the MySQL CREATE TRIGGER Syntax reference.
But are you sure that you need to call an executable right away when the row is inserted? It seems like that method will be prone to failure, because MySQL might spawn multiple instances of the executable at the same time. If your executable fails, then there will be no record of which rows have been processed yet and which have not. If MySQL is waiting for your executable to finish, then inserting rows might be very slow. Also, if Chad Birch is right, then will have to recompile MySQL, so it sounds difficult.
Instead of calling the executable directly from MySQL, I would use triggers to simply record the fact that a row got INSERTED or UPDATED: record that information in the database, either with new columns in your existing tables or with a brand new table called say database_changes. Then make an external program that regularly reads the information from the database, processes it, and marks it as done.
Your specific solution will depend on what parameters the external program actually needs.
If your external program needs to know which row was inserted, then your solution could be like this: Make a new table called database_changes with fields date, table_name, and row_id, and for all the other tables, make a trigger like this:
CREATE TRIGGER `my_trigger`
AFTER INSERT ON `table_name`
FOR EACH ROW BEGIN
INSERT INTO `database_changes` (`date`, `table_name`, `row_id`)
VALUES (NOW(), "table_name", NEW.id)
END;
Then your batch script can do something like this:
Select the first row in the database_changes table.
Process it.
Remove it.
Repeat 1-3 until database_changes is empty.
With this approach, you can have more control over when and how the data gets processed, and you can easily check to see whether the data actually got processed (just check to see if the database_changes table is empty).
you could do what replication does: hang on the 'binary log'. setup your server as a 'master server', and instead of adding a 'slave server', run mysqlbinlog. you'll get a stream of every command that modifies your database.
step in 'between' the client and server: check MySQLProxy. you point it to your server, and point your client(s) to the proxy. it lets you interpose Lua scripts to monitor, analyze or transform any SQL command.
I think it's going to require adding a User-Defined Function, which I believe requires recompilation:
MySQL FAQ - Triggers: Can triggers call an external application through a UDF?
I think it's really a MUCH better idea to have some external process poll changes to the table and execute the external program - you could also have a column which contains the status of this external program run (e.g. "pending", "failed", "success") - and just select rows where that column is "pending".
It depends how soon the batch job needs to be run. If it's something which needs to be run "sooner or later" and can fail and need to be retried, definitely have an app polling the table and running them as necessary.