jerry post mcgraw-hill/irwin copyright © 2005 by the mcgraw-hill companies, inc. all rights...
Post on 19-Dec-2015
215 views
TRANSCRIPT
Jerry PostJerry Post
McGraw-Hill/Irwin Copyright © 2005 by The McGraw-Hill Companies, Inc. All rights reserved.
Database Management SystemsDatabase Management Systems
Chapter 7
Database Integrity and
Transactions
2
DDAATTAABBAASSEE
DBMS
Programming Environment
Create code(1) Within the query system
(2) In forms and reports
(3) Hosted in external programs
Tables
Forms &Reports
Queries
If (Click) ThenMsgBox . . .
End If
If ( . . ) Then SELECT . . .
Else . . .UPDATE . . .
End If
C++
ExternalProgram
if (. . .) { // embed SQL SELECT …}
(2)
(1)
(3)
3
DDAATTAABBAASSEE
User-Defined Function
CREATE FUNCTION EstimateCosts (ListPrice Currency, ItemCategory VarChar)
RETURNS CurrencyBEGIN
IF (ItemCategory = ‘Clothing’) THENRETURN ListPrice * 0.5
ELSERETURN ListPrice * 0.75
END IFEND
4
DDAATTAABBAASSEE
Function to Perform Conditional Update
CREATE FUNCTION IncreaseSalary(EmpID INTEGER, Amt CURRENCY)
RETURNS CURRENCYBEGIN
IF (Amt > 50000) THENRETURN -1 -- error flag
ENDUPDATE Employee SET Salary = Salary + AmtWHERE EmployeeID = EmpID;RETURN Amt
END
5
DDAATTAABBAASSEE
Looking Up Data
CREATE FUNCTION IncreaseSalary(EmpID INTEGER, Amt CURRENCY)
RETURNS CURRENCYDECLARE
CURRENCY MaxAmount;BEGIN
SELECT MaxRaise INTO MaxAmountFROM CompanyLimitsWHERE LimitName = ‘Raise’;
IF (Amt > 50000) THENRETURN -1 -- error flag
ENDUPDATE Employee SET Salary = Salary + AmtWHERE EmployeeID = EmpID;RETURN Amt;
END
6
DDAATTAABBAASSEE
Data Trigger Events
Oracle additions: Tables ALTER, CREATE, DROP User LOGOFF, LOGON Database SERVERERROR, SHUTDOWN, STARTUP
INSERT
DELETE
UPDATE
BEFORE AFTER
7
DDAATTAABBAASSEE
Statement v. Row Triggers
UPDATE EmployeeSET Salary = Salary + 10000WHERE EmployeeID=442 OR EmployeeID=558
SQL
time
Before UpdateOn table
After UpdateOn table
Before UpdateRow 442
After UpdateRow 442
UpdateRow 442
… other rows
Triggers for overall table
Triggers for each row
8
DDAATTAABBAASSEE
Data Trigger Example
CREATE TRIGGER LogSalaryChangesAFTER UPDATE OF Salary ON EmployeeREFERENCING OLD ROW as oldrow
NEW ROW AS newrowFOR EACH ROW
INSERT INTO SalaryChanges (EmpID, ChangeDate, User, OldValue, NewValue)VALUES (newrow.EmployeeID, CURRENT_TIMESTAMP,CURRENT_USER, oldrow.Salary, newrow.Salary);
9
DDAATTAABBAASSEE
Canceling Data Changes in Triggers
CREATE TRIGGER TestDeletePresidentBEFORE DELETE ON EmployeeREFERENCING OLD ROW AS oldrowFOR EACH ROW
WHEN (oldrow.Title = ‘President’)SIGNAL _CANNOT_DELETE_PRES;
10
DDAATTAABBAASSEE
Cascading Triggers
Sale(SaleID, SaleDate, …)
OrderItem(OrderID, ItemID, Quantity, …)
Order(OrderID, OrderDate, …)
Inventory(ItemID, QOH, …)
SaleItem(SaleID, ItemID, Quantity, …)
AFTER INSERTUPDATE InventorySET QOH = QOH – newrow.Quantity
AFTER UPDATEWHEN newrow.QOH < newrow.Reorder
INSERT {new order}INSERT {new OrderItem}
11
DDAATTAABBAASSEE
Trigger LoopEmployee(EID, Salary)
BonusPaid(EID, BonusDate, Amount)
StockOptions(EID, OptionDate, Amount, SalaryAdj)
AFTER UPDATEIF newrow.Salary > 100000 THEN
Add BonusEND
AFTER UPDATE Or INSERTIF newrow.Bonus > 50000 THEN
Reduce BonusAdd Options
END
AFTER UPDATE Or INSERTIF newrow.Amount > 100000 THEN
Reduce SalaryEND
12
DDAATTAABBAASSEE
Transactions Some transactions result in multiple
changes. These changes must all be
completed successfully, or the group must fail.
Protection for hardware and communication failures.
example: bank customer transfers money from savings account to checking account.
Decrease savings balance Increase checking balance Problem if one transaction and
machine crashes.
Possibly: give users a chance to reverse/undo a transaction.
Performance gain by executing transactions as a block.
Savings Accounts
Inez: 5340.924340.92
Checking Accounts
Inez: 1424.27
Transaction1. Subtract $1000 from savings.
(machine crashes)2. Add $1000 to Checking.
(money disappears)
$1000
13
DDAATTAABBAASSEE
Defining Transactions
The computer needs to be told which changes must be grouped into a transaction.Turn on transaction processing.Signify a transaction start.Signify the end.
Success: save all changesFailure: cancel all changes
Must be set in module codeCommitRollback
14
DDAATTAABBAASSEE
SQL Transaction CodeCREATE FUNCTION TransferMoney(Amount Currency, AccountFrom Number,
AccountTo Number) RETURNS NUMBERcurBalance Currency;BEGIN
DECLARE HANDLER FOR SQLEXCEPTIONBEGIN
ROLLBACK;Return -2; -- flag for completion error
END;START TRANSACTION; -- optionalSELECT CurrentBalance INTO curBalance FROM Accounts WHERE (AccountID = AccountFrom);IF (curBalance < Amount) THEN
RETURN -1; -- flag for insufficient fundsEND IFUPDATE Accounts SET CurrentBalance = CurrentBalance – AmountWHERE AccountID = AccountFrom;UPDATE AccountsSET CurrentBalance = CurrentBalance + AmountWHERE AccountID = AccountTo;COMMIT;RETURN 0; -- flag for success
END;
15
DDAATTAABBAASSEE
SAVEPOINT
START TRANSACTION;SELECT …UPDATE …SAVEPOINT StartOptional;UPDATE …UPDATE …If error THEN
ROLLBACK TO SAVEPOINT StartOptional;END IFCOMMIT;
time
startRequired elements
SAVEPOINTStartOptional
Risky stepscommit
Partial rollback
16
DDAATTAABBAASSEE
Concurrent Access Concurrent Access
Multiple users or processes changing the same data at the same time.
Final data will be wrong!
Force sequentialLockingDelayed, batch updates
Two processesReceive payment ($200)Place new order ($150)
Initial balance $800Result should be $800 -
200 + 150 = $750 Interference result is
either $600 or $950
ID BalanceJones $800
$600$950
Customers
1) Read balance 8002) Subtract pmt -2004) Save new bal. 600
3) Read balance 8005) Add order 1506) Write balance 950
Receive Payment Place New Order
17
DDAATTAABBAASSEE
Pessimistic Locks: Serialization
One answer to concurrent access is to prevent it. When a transaction needs to alter data, it places a
SERIALIZABLE lock on the data used, so no other transactions can even read the data until the first transaction is completed.
ID BalanceJones $800
$600
Customers
1) Read balance 8002) Subtract pmt -2004) Save new bal. 600
3) Read balanceReceive error message that it is locked.
Receive Payment Place New Order
SET TRANSACTION SERIALIZABLE, READ WRITE
18
DDAATTAABBAASSEE
SQL Pessimistic Lock
CREATE FUNCTION ReceivePayment (AccountID NUMBER, Amount Currency) RETURNS NUMBER
BEGINDECLARE HANDLER FOR SQLEXCEPTIONBEGIN
ROLLBACK;RETURN -2;
ENDSET TRANSACTION SERIALIZABLE, READ WRITE;UPDATE AccountsSET AccountBalance = AccountBalance - AmountWHERE AccountNumber = AccountID;COMMIT;RETURN 0;
END
19
DDAATTAABBAASSEE
Deadlock
DeadlockTwo (or more) processes have
placed locks on data and are waiting for the other’s data.
Many solutionsRandom wait timeGlobal lock managerTwo-phase commit - messages
Data A Data B
1) Lock Data A3) Wait for Data B
2) Lock Data B4) Wait for Data A
20
DDAATTAABBAASSEE
Lock Manager
ResourceA
ResourceB
ResourceC
ResourceD
ResourceE
Process1 Lock Wait
Process2 Wait Lock
Process3 Lock
Process4 Lock Wait
Process5 Wait
Process6 Wait Lock
Process7 Wait Wait
21
DDAATTAABBAASSEE
Optimistic Locks
Assume that collisions are rare Improved performance, fewer resources Allow all code to read any data (no locks) When code tries to write a new value
Check to see if the existing value is different from the one you were given earlier
If it is different, someone changed the database before you finished, so it is a collision--raise an error
Reread the value and try again
22
DDAATTAABBAASSEE
Optimistic Locks for Simple Update
(1) Read the balance
(2) Add the new order value
(3) Write the new balance
(4) Check for errors
(5) If there are errors, go back to step (1).
23
DDAATTAABBAASSEE
Optimistic Locks with SQLCREATE FUNCTION ReceivePayment (
AccountID NUMBER, Amount Currency) RETURNS NUMBERoldAmount Currency;testEnd Boolean = FALSE;BEGIN
DO UNTIL testEnd = TRUEBEGIN
SELECT Amount INTO oldAmountWHERE AccountNumber = AccountID;…UPDATE AccountsSET AccountBalance = AccountBalance - AmountWHERE AccountNumber = AccountIDAND Amount = oldAmount;COMMIT;IF SQLCODE = 0 and nrows > 0 THEN
testEnd = TRUE;RETURN 0;
END IF-- keep a counter to avoid infinite loops
ENDEND
24
DDAATTAABBAASSEE
ACID Transactions
Atomicity: all changes succeed or fail together. Consistency: all data remain internally consistent
(when committed) and can be validated by application checks.
Isolation: The system gives each transaction the perception that it is running in isolation. There are no concurrent access issues.
Durability: When a transaction is committed, all changes are permanently saved even if there is a hardware or system failure.
25
DDAATTAABBAASSEE
SQL 99/200x Isolation Levels READ UNCOMMITTED
Problem: might read dirty data that is rolled back Restriction: not allowed to save any data
READ COMMITTED Problem: Second transaction might change or delete data Restriction: Need optimistic concurrency handling
REPEATABLE READ Problem: Phantom rows
SERIALIZABLE Provides same level of control as if all transactions were run
sequentially. But, still might encounter locks and deadlocks
26
DDAATTAABBAASSEE
Phantom RowsSELECT SUM(QOH)FROM InventoryWHERE Price BETWEEN 10 and 20
UPDATE InventorySET Price = Price/2WHERE …
ItemID QOH Price
111 5 15
113 6 7
117 12 30
118 4 12
119 7 22
120 8 17
Included in first query
SELECT SUM(QOH)FROM InventoryWHERE Price BETWEEN 10 and 20
Additional rows will be included in the second query
27
DDAATTAABBAASSEE
Generated Keys
Create an order for a new customer:
(1) Create new key for CustomerID(2) INSERT row into Customer(3) Create key for new OrderID(4) INSERT row into Order
Customer Table
CustomerID, Name, …
Order Table
OrderID, CustomerID, …
28
DDAATTAABBAASSEE
Methods to Generate Keys
1. The DBMS generates key values automatically whenever a row is inserted into a table.
Drawback: it is tricky to get the generated value to use it in a second table.
2. A separate key generator is called by a programmer to create a new key for a specified table.
Drawback: programmers have to write code to generate a key for every table and each row insertion.
Overall drawbacks: neither method is likely to be transportable. If you change the DBMS, you will have to rewrite the procedures to generate keys.
29
DDAATTAABBAASSEE
Auto-Generated Keys
Create an order for a new customer:
(1) INSERT row into Customer(2) Get the key value that was generated(3) Verify the key value is correct. How?(4) INSERT row into Order
Major problem:Step 2 requires that the DBMS return the key value that was most recently generated. How do you know it is the right value? What happens if two transactions generate keys at almost the same time on the same table?
30
DDAATTAABBAASSEE
Key-Generation Routine
Create an order for a new customer:
(1) Generate a key for CustomerID(2) INSERT row into Customer(3) Generate a key for OrderID(4) INSERT row into Order
This method ensures that unique keys are generated, and that you can use the keys in multiple tables because you know the value. But, none of it is automatic. It always requires procedures and sometimes data triggers.
31
DDAATTAABBAASSEE
Database Cursors
PurposeTrack through table or
query one row at a time.Data cursor is a pointer to
active row.
Why?Performance.SQL cannot do everything.
Complex calculations.Compare multiple rows.
Year Sales1998 104,3211999 145,9982000 276,0042001 362,736
1998 104,3211999 145,9982000 276,0042001 362,736
32
DDAATTAABBAASSEE
Database Cursor Program StructureDECLARE cursor1 CURSOR FOR
SELECT AccountBalanceFROM Customer;
sumAccount, balance Currency;SQLSTATE Char(5);BEGIN
sumAccount = 0;OPEN cursor1;WHILE (SQLSTATE = ‘00000’)BEGIN
FETCH cursor1 INTO balance;IF (SQLSTATE = ‘00000’) THEN
sumAccount = sumAccount + balance;END IF
ENDCLOSE cursor1;-- display the sumAccount or do a calculation
END
33
DDAATTAABBAASSEE
Cursor Positioning with FETCH
DECLARE cursor2 SCROLL CURSOR FORSELECT …OPEN cursor2;FETCH LAST FROM cursor2 INTO …Loop…
FETCH PRIOR FROM cursor2 INTO …End loopCLOSE cursor2;
FETCH positioning options:FETCH NEXT next rowFETCH PRIOR prior rowFETCH FIRST first rowFETCH LAST last rowFETCH ABSOLUTE 5 fifth rowFETCH RELATIVE -3 back 3 rows
34
DDAATTAABBAASSEE
Problems with Multiple Users
Name SalesAlice 444,321Carl 254,998Donna 652,004Ed 411,736
Original Data
Name SalesAlice 444,321Bob 333,229Carl 254,998Donna 652,004Ed 411,736
Modified Data
New row isadded--whilecode is running.
The SQL standard can prevent this problem with the INSENSITIVE option:
DECLARE cursor3 INSENSITIVE CURSOR FOR …
But, this is an expensive approach, because the DBMS usually makes a copy of the data. Instead, avoid moving backwards.
35
DDAATTAABBAASSEE
Changing Data with Cursors
Year Sales Gain
2000 151,039
2001 179,332
2002 195,453
2003 221,883
2004 223,748
DECLARE cursor1 CURSOR FORSELECT Year, Sales, GainFROM SalesTotalORDER BY YearFOR UPDATE OF Gain;priorSales, curYear, curSales, curGainBEGIN
priorSales = 0;OPEN cursor1;Loop:
FETCH cursor1 INTO curYear, curSales, curGainUPDATE SalesTotalSET Gain = Sales – priorSalesWHERE CURRENT OF cursor1;priorSales = curSales;
Until end of rowsCLOSE cursor1;COMMIT;
END
36
DDAATTAABBAASSEE
Dynamic Parameterized Cursor Queries
DECLARE cursor2 CURSOR FORSELECT ItemID, Description, PriceFROM InventoryWHERE Price < :maxPrice;maxPrice Currency;BEGIN
maxPrice = … -- from user or other queryOPEN cursor2; -- runs query with current valueLoop:
-- Do something with the rows retrievedUntil end of rowsCLOSE cursor2;
END
Parameters enable you to control the rows retrieved dynamically from within the procedure code. The value is applied when the cursor is opened.
37
DDAATTAABBAASSEE
Sally’s Pet Store Inventory
Inventory method 1: calculate the current quantity on hand by totaling all purchases and sales every time the total is needed.Drawback: performance
Inventory method 2: keep a running balance in the inventory table and update it when an item is purchased or sold.Drawback: tricky code
Also, you need an adjustment process for “inventory shrink”
38
DDAATTAABBAASSEE
Inventory QuantityOnHand
ItemIDDescriptionQuantityOnHandListPriceCategory
Merchandise
Add items purchased
Subtract items sold
Adjust for shrink
SaleIDItemIDQuantitySalePrice
SaleItem
39
DDAATTAABBAASSEE
Inventory Events For a new sale, a row is added to
the SaleItem table. A sale or an item could be
removed because of a clerical error or the customer changes his or her mind. A SaleItem row will be deleted.
An item could be returned, or the quantity could be adjusted because of a counting error. The Quantity is updated in the SaleItem table.
An item is entered incorrectly. ItemID is updated in the SaleItem table.
SaleIDItemIDQuantitySalePrice
SaleItem
(1) Add a row.
(2) Delete a row.
(3) Update Quantity.
(4) Update ItemID.
40
DDAATTAABBAASSEE
New Sale: Insert SaleItem Row
CREATE TRIGGER NewSaleItemAFTER INSERT ON SaleItemREFERENCING NEW ROW AS newrowFOR EACH ROW
UPDATE MerchandiseSET QuantityOnHand = QuantityOnHand – newrow.QuantityWHERE ItemID = newrow.ItemID;
41
DDAATTAABBAASSEE
Delete SaleItem Row
CREATE TRIGGER DeleteSaleItemAFTER DELETE ON SaleItemREFERENCING OLD ROW AS oldrowFOR EACH ROW
UPDATE MerchandiseSET QuantityOnHand = QuantityOnHand + oldrow.QuantityWHERE ItemID = oldrow.ItemID;
42
DDAATTAABBAASSEE
Quantity Changed Event
CREATE TRIGGER UpdateSaleItemAFTER UPDATE ON SaleItemREFERENCING OLD ROW AS oldrow
NEW ROW AS newrowFOR EACH ROW
UPDATE MerchandiseSET QuantityOnHand = QuantityOnHand
+ oldrow.Quantity – newrow.QuantityWHERE ItemID = oldrow.ItemID;
43
DDAATTAABBAASSEE
ItemID or Quantity Changed Event
CREATE TRIGGER UpdateSaleItemAFTER UPDATE ON SaleItemREFERENCING OLD ROW AS oldrow
NEW ROW AS newrowFOR EACH ROWBEGIN
UPDATE MerchandiseSET QuantityOnHand = QuantityOnHand + oldRow.QuantityWHERE ItemID = oldrow.ItemID;
UPDATE MerchandiseSET QuantityOnHand = QuantityOnHand – newRow.QuantityWHERE ItemID = newrow.ItemID;COMMIT;
END