Audit Log Script using Triggers - mysql

Audit Logs for 50 tables need to insert in one table called audit table whatever the event performed on the tables(insert,update,delete) occurs it should contain new_val,old_val and table name,class name,modified by like these fields into my Audit Table.50 tables data should contain only in one single table called Audit Table
It is showing that i need to write script for every table how many tables it contains

If you will use triggers on your other tables to insert rows into your audit log table, you will indeed need to write three triggers for each table. (ON INSERT, ON UPDATE, ON DELETE).
Pain in the xxx. Triple pain in the xxx. Sigh.
If this were my project I'd consider writing a program to query information_schema.TABLES for a list of the tables involved, and generate the CREATE TRIGGER code for the tables involved. But, depending on the complexity of your table structure, that might be more trouble than it's worth.
Maybe helpful: create trigger insert update delete in 1 syntax

Related

CREATE TABLE IF NOT EXISTS vs SHOW TABLES LIKE

In MySQL, which is a better practice? Always use "CREATE TABLE IF NOT EXISTS", or check first the existence of the table using "SHOW TABLES LIKE" before making the table?
I have to regularly save a page where the table for it may or may not be there (sometimes, it is deliberately deleted when not in use). Previously, I used to do "SHOW TABLES LIKE" to check if that table exists before I insert new entries. But I changed it to "CREATE TABLE IF NOT EXISTS". Either way, I just do a "INSERT .. ON DUPLICATE UPDATE" to add new or update existing data.
I don't know how to benchmark this, which is why I am asking.
Performance isn't critical with these operations.
The key aspect is race conditions. If you use CREATE TABLE IF NOT EXISTS you know it will happen or it won't. If two threads happen to be doing this statement one will succeed and the other won't be negatively affected.
If a SHOW TABLE LIKE was used in both threads, both could detect the table didn't exist, and upon trying to create the table, one would fail.
So use CREATE TABLE IF NOT EXISTS to mitigate race conditions. Also in general is better to use a database provided feature than roll your own.
CREATE TABLE IF NOT EXISTS is option provided by MySQL and good to use. If table will not exist this statement will create else will skip.
other end, if you first check table existence by show table like then either skip or create as per result of condition/check. Ultimately you are increasing one step or runtime of you script or program for same functionality which you can achieve in single step.

Create a view or new table for caching records

I'm experiencing huge performance problem in one legacy application.
There is a search form where user can search records with given value.
A result row contains 10 columns. Then a SP returns any row which contains in any column that value.
This SP uses 8 Tables and some of them have about million records. Every minute I get a new record. This SP conducts paging as well.
Execution of this SP takes sometimes around 40 seconds.
What I did was, I created a new table and put there all records by using a query from this SP, but without conditions.
When there is a new update or update in one of source table I use a trigger and update this new "cache" table.
Now waiting for results from this new table takes only 1-3 seconds.
Has someone experience with something like this?
One of my colleagues said I better use view, but then every time I will be making JOINS.
What do you think? Is there another way?
Often times temporary tables can help you resolve performance issues. One approach might be to collect only the records that you need to consider into temporary tables and then create your final select statement from the temporary tables joined to any other tables that you're not filtering.
As an example, let's say one of the fields you are searching for is field1 in table1. Start by inserting into table #table1 only records that have the value of field1 you are looking for:
select PrimaryKeyTable1, Field1, Field2, Field3, etc...
into #table1
from table1
where Field1 = 'Whatever you are looking for'
This should be pretty fast even for a big tables, especially if you have an index on Field1. You do this for every table with search fields to collect all the records that have relevant records you are searching.
Then you also need to be sure to insert any records into your temporary tables that might have foreign key references to any of your other temporary tables. So let's say you also built a table #table2 with the above method that has a foreign key to table1 called PrimaryKeyTable1. You would insert those records like:
Insert into #table1
(PrimaryKeyTable1, Field1, Field2, Field3, etc...)
select table1.PrimaryKeyTable1, table1.Field1, table1.Field2, table1.Field3, etc...
from table1
join #table2
on table1.PrimaryKeyTable1 = table2.PrimaryKeyTable1
where table1.PrimaryKeyTable1 not in
(Select PrimaryKeyTable1 from #table1)
Now you will also have any records in #table1 that match to a record in #table2 that contain records that match the search criteria. You do this for all your temporary tables that have relevant foreign keys. The order that you do the inserts matters; be sure that you don't reference any temporary tables until after the last insert statement while collecting the foreign key referenced records.
Then you can simply do your final select statement, replacing the actual tables with the temporary tables you have built and eliminating all the filters that search your field data. Depending on the structure of your query there might be other optimizations, but that is the general idea.
If you've already explored all of your indexing options and this still doesn't help, MS SQL Server has "Change Tracking" features that maybe be of use to you in building your cache table. You enable the database for change tracking and configure which tables you wish to track. SQL Server then creates change records on every update, insert, delete on a table and then lets you query for changes to records that have been made since the last time you checked. This is very useful for syncing changes and is more efficient than using triggers. It's also easier to manage than making your own tracking tables. This has been a feature since SQL Server 2005.
How to: Use SQL Server Change Tracking
Change tracking only captures the primary keys of the tables and let's you query which fields might have been modified. Then you can query the tables join on those keys to get the current data. If you want it to capture the data also you can use Change Capture, but it requires more overhead and at least SQL Server 2008 enterprise edition.
Change Data Capture
Your solution is a robust way of doing what is called in Microsoft SQL Server "an indexed view" or "materialized view" in Oracle.
Basically you are correct - it's faster to navigate single indexed table then a dozen ones which are updated constantly.
You should really try creating an indexed view (some start here https://technet.microsoft.com/en-us/library/dd171921(v=sql.100).aspx) and it will probably solve all your performance issues.
You can use schema binding View and create cluster index on view.it will store your view data physically.but after creating schema binding view you can not alter your table.

How to automatically run a query when a table is amended by INSERT/UPDATE/DELETE?

I have a query which basically "syncs" all the data from a table in one database, to a replicated table in another database.
Here is the simple query:
TRUNCATE TABLE [Database2].[dbo].[USER_SYNC]
INSERT INTO [Database2].[dbo].[USER_SYNC]
SELECT * FROM [Database1].[dbo].[USER]
Now, after some research, I had a look into using a trigger to do this, however, I read up that stored procedures and heavy queries such as this should not be used within a trigger.
Therefore, what is the best way in which I can automatically run this query from within SQL, whenever a record in database1 is inserted, amended or deleted?
And if what I read up about triggers was incorrect, then how would I go about creating one for my procedure? Thanks.
If you need to sync tables you do not need to truncate one every time on update, delete or insert.
Create identical copy of user table.
Create on update, on delete, on insert triggers on the original user table.
In the trigger update, delete or insert to the duplicate table only one row at a time - the one that was updated, deleted or inserted to the original user table. This will not be a heavy query.
UPDATE:
http://www.mysqltutorial.org/create-the-first-trigger-in-mysql.aspx
http://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html

Record at column level changes in mysql table

My client wants to maintain audit at column level. He wants a table which stores all the audits i.e. at column level. I have decided on a table structure. i.e
id,tablename,tablecolumn,primarkey,oldvalue,newvalue,date
But i was wondering how will i check for each column level changes. Do i have to check each one manually like old.columnname <> new.columnname and then add into audit table ?
Is there any other way to do it.
When I was given the same task, I've created several stored procedures for modifying table data and restricted CUD operations on table to force users to use only stored procedures.
SPs were actually performing the action requested (i.e. create, update or delete a row in table) plus adding a line to the audit table for every action.
This might be quite inefficient from DB optimization point of view but I think it gives you the most of auditing as update operation and audit are automatically put in a transaction and update can not be completed without adding an audit entry.

SQL Table Custom AVG

I have to create a particular system of reviews in which I should do a lot of AVG in my query, so I want to ask if it's possible to create a table in SQL in which I have these Averages automatically updated?
Mysql 5.5.24-0ubuntu0.12.04.1
Yes, there are two ways to do this:
You can create a "view", which is like a table, except that its records come from a SQL query (usually derived from other tables) rather than being stored directly. See http://dev.mysql.com/doc/refman/5.6/en/create-view.html.
You can create a "trigger", which is procedural code that runs whenever a specified table is modified in a specified way. In your case, you would create a trigger that runs whenever one table is modified, and that re-generates the secondary table. See http://dev.mysql.com/doc/refman/5.6/en/create-trigger.html.