We programatically create and update customer records. When a customer logs on to our system, we authenticate through our ERP and then create a Magento (1.4.0.1-Yes I *KNOW* it's old) user record with the data that came from our ERP. Then we set the same password for all users so that we can also automatically log them on.
When a user already has a record, we search for them by email address and update their record with the info that came from our ERP.
After the customer record is saved:
$customer->save();
we delete all their addresses and then insert new addresses based on the info that came from the ERP.
When calling save on the addresses:
$bizaddress->save();
We are getting a SQL Deadlock exception.
[29-Sep-2015 18:37:40] PHP Fatal error: Uncaught exception 'Zend_Db_Statement_Exception' with message 'SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction' in /srv/www/htdocs/store/lib/Zend/Db/Statement/Pdo.php:243 Stack trace: #0 /srv/www/htdocs/store/lib/Zend/Db/Statement.php(300): Zend_Db_Statement_Pdo->_execute(Array) #1 /srv/www/htdocs/store/lib/Zend/Db/Adapter/Abstract.php(468): Zend_Db_Statement->execute(Array) #2 /srv/www/htdocs/store/lib/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract->query('UPDATE `magcust...', Array) #3 /srv/www/htdocs/store/lib/Varien/Db/Adapter/Pdo/Mysql.php(333): Zend_Db_Adapter_Pdo_Abstract->query('UPDATE `magcust...', Array) #4 /srv/www/htdocs/store/lib/Zend/Db/Adapter/Abstract.php(604): Varien_Db_Adapter_Pdo_Mysql->query('UPDATE `magcust...', Array) #5 /srv/www/htdocs/store/app/code/core/Mage/Eav/Model/Entity/Abstract.php(1133): Zend_Db_Adapter_Abstract->update('magcustomer_ent...', Array, 'entity_id='7154...') #6 /srv/www/htdocs/store/app in /srv/www/htdocs/store/lib/Zend/Db/Statement/Pdo.php on line 243
Is still having the $customer object open, not calling unset($customer); the culprit here? What could be causing this as we are inserting 2 addresses as shown below.
// $PInfo is data returned from ERP
// Save customer name, even if it's existing, in case it changed.
$customer->setFirstname($PInfo['FirstName']);
$customer->setLastname($PInfo['LastName']);
try {
$customer->save();
$ret['result'] = 'SUCCESS';
} catch (Exception $e) {
$ret['result'] = 'FAILURE';
$ret['error'] .= $e->getMessage();
return $ret;
}
$mailpref = $PInfo['MailingPreference'];
$shippref = $PInfo['Shippingpreference'];
$addfname = $PInfo['FirstName'];
$addlname = $PInfo['LastName'];
$addpfix = $PInfo['Prefix'];
$biz['addstreet1'] = null;
$home['addstreet1'] = null;
if (trim($PInfo['BusinessAddress1']) != '') {
$biz['addstreet1'] = trim($PInfo['BusinessAddress1']);
$biz['addstreet2'] = trim($PInfo['BusinessAddress2']);
$biz['addstreet3'] = trim($PInfo['BusinessAddress3']);
$biz['addcity'] = $PInfo['BusinessCity'];
$biz['addstate'] = $PInfo['BusinessState'];
$biz['addzip'] = $PInfo['BusinessZip'];
$biz['addcountry'] = $PInfo['BusinessCountry'];
$biz['addphone'] = $PInfo['BusinessPhone'];
}
if (trim($PInfo['HomeAddress1']) != '') {
$home['addstreet1'] = trim($PInfo['HomeAddress1']);
$home['addstreet2'] = trim($PInfo['HomeAddress2']);
$home['addstreet3'] = trim($PInfo['HomeAddress3']);
$home['addcity'] = $PInfo['HomeCity'];
$home['addstate'] = $PInfo['HomeState'];
$home['addzip'] = $PInfo['HomeZip'];
$home['addcountry'] = $PInfo['HomeCountry'];
$home['addphone'] = $PInfo['HomePhone'];
}
$cid = $customer->getId();
// Should I unset $customer here????
// unset($customer);
// Removing old Addresses, then adding them fresh from the API
foreach ($customer->getAddresses() as $address) {
$address->delete();
}
// Adding Business Address
if (!is_null($biz['addstreet1'])) {
if (trim($biz['addcountry']) == '') {
$biz['addcountry'] = 'US';
}
/*
Have to get the region id from the state name
*/
$regionModel = Mage::getModel('directory/region')->loadByCode($biz['addstate'], $biz['addcountry']);
$regionId = $regionModel->getId();
$bizaddress = Mage::getModel("customer/address");
$bizaddress->setCustomerId($cid);
$bizaddress->firstname = $addfname;
$bizaddress->lastname = $addlname;
$bizaddress->prefix = $addpfix;
$bizaddress->country_id = $biz['addcountry'];
$bizaddress->postcode = $biz['addzip'];
$bizaddress->city = $biz['addcity'];
$bizaddress->region = $regionId;
$bizaddress->street = array('0'=>$biz['addstreet1'],'1'=>$biz['addstreet2'],'2'=>$biz['addstreet3']);
if($mailpref == 1 || $mailpref == 0) {
$bizaddress->setIsDefaultBilling('1');
}
if($shippref == 1) {
$bizaddress->setIsDefaultShipping('1');
}
$bizaddress->setSaveInAddressBook('1');
$bizaddress->telephone = (array_key_exists('addphone', $biz)?$biz['addphone']:"---");
$bizaddress->save(); // THIS IS THE LINE WHERE THE SQL DEADLOCK OCCURS
}
// Adding Home Address
if (!is_null($home['addstreet1'])) {
if (trim($home['addcountry']) == '') {
$home['addcountry'] = 'US';
}
$regionModel = Mage::getModel('directory/region')->loadByCode($home['addstate'], $home['addcountry']);
$regionId = $regionModel->getId();
$homeaddress = Mage::getModel("customer/address");
$homeaddress->setCustomerId($cid);
$homeaddress->firstname = $addfname;
$homeaddress->lastname = $addlname;
$homeaddress->country_id = $home['addcountry'];
$homeaddress->postcode = $home['addzip'];
$homeaddress->city = $home['addcity'];
$homeaddress->region = $regionId;
$homeaddress->street = array('0'=>$home['addstreet1'],'1'=>$home['addstreet2'],'2'=>$home['addstreet3']);
$homeaddress->telephone = $home['addphone'];
if($mailpref == 2) {
$homeaddress->setIsDefaultBilling('1');
}
if($shippref == 2) {
$homeaddress->setIsDefaultShipping('1');
}
$homeaddress->setSaveInAddressBook('1');
$homeaddress->save();
}
// login new customer
Mage::getSingleton('core/session', array('name'=>'frontend'));
$session = Mage::getSingleton('customer/session');
$session->login($PInfo['EmailAddress'],'same_password_as_all_accounts');
$session->setCustomerAsLoggedIn($session->getCustomer());
Hi,
I use some very similar code to this and the main difference is where I delete customer addresses I use the following:
$addresses = $customer->getAddressCollection() ->setCustomerFilter($customer); foreach($addresses as $address){ $address->delete(); }
I then re-add them with something like:
$address = Mage::getModel('customer/address'); $address->setFirstname($customer->getName()) ->setLastname($customer->getName()) ->setCompany($customer->getName()) ->setStreet($street) // etc ... ->save();
Hopefuly this helps!
Will test this out, looks like it will work but not sure if it will solve the deadlocks issue.
That did not help with the deadlock issue although it made the code somewhat shorter ;-)
Hi,
I can't really say for sure then..
I would have your MySQL processlist open whilst your script is running and see which queries stack up and take it from there.
Not really sure how to do that.